net/bnxt: fix build
[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 #include "ulp_port_db.h"
22 #include "ulp_ha_mgr.h"
23 #include "bnxt_tf_pmd_shim.h"
24
25 static uint8_t mapper_fld_zeros[16] = { 0 };
26
27 static uint8_t mapper_fld_ones[16] = {
28         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
29         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
30 };
31
32 static uint8_t mapper_fld_one[16] = {
33         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
34         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
35 };
36
37 static const char *
38 ulp_mapper_tmpl_name_str(enum bnxt_ulp_template_type tmpl_type)
39 {
40         switch (tmpl_type) {
41         case BNXT_ULP_TEMPLATE_TYPE_CLASS:
42                 return "class";
43         case BNXT_ULP_TEMPLATE_TYPE_ACTION:
44                 return "action";
45         default:
46                 return "invalid template type";
47         }
48 }
49
50 static struct bnxt_ulp_glb_resource_info *
51 ulp_mapper_glb_resource_info_list_get(uint32_t *num_entries)
52 {
53         if (!num_entries)
54                 return NULL;
55         *num_entries = BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
56         return ulp_glb_resource_tbl;
57 }
58
59 /*
60  * Read the global resource from the mapper global resource list
61  *
62  * The regval is always returned in big-endian.
63  *
64  * returns 0 on success
65  */
66 static int32_t
67 ulp_mapper_glb_resource_read(struct bnxt_ulp_mapper_data *mapper_data,
68                              enum tf_dir dir,
69                              uint16_t idx,
70                              uint64_t *regval,
71                              bool *shared)
72 {
73         if (!mapper_data || !regval || !shared ||
74             dir >= TF_DIR_MAX || idx >= BNXT_ULP_GLB_RF_IDX_LAST)
75                 return -EINVAL;
76
77         *regval = mapper_data->glb_res_tbl[dir][idx].resource_hndl;
78         *shared = mapper_data->glb_res_tbl[dir][idx].shared;
79         return 0;
80 }
81
82 /*
83  * Write a global resource to the mapper global resource list
84  *
85  * The regval value must be in big-endian.
86  *
87  * return 0 on success.
88  */
89 static int32_t
90 ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data *data,
91                               struct bnxt_ulp_glb_resource_info *res,
92                               uint64_t regval, bool shared)
93 {
94         struct bnxt_ulp_mapper_glb_resource_entry *ent;
95
96         /* validate the arguments */
97         if (!data || res->direction >= TF_DIR_MAX ||
98             res->glb_regfile_index >= BNXT_ULP_GLB_RF_IDX_LAST)
99                 return -EINVAL;
100
101         /* write to the mapper data */
102         ent = &data->glb_res_tbl[res->direction][res->glb_regfile_index];
103         ent->resource_func = res->resource_func;
104         ent->resource_type = res->resource_type;
105         ent->resource_hndl = regval;
106         ent->shared = shared;
107         return 0;
108 }
109
110 /*
111  * Internal function to allocate identity resource and store it in mapper data.
112  *
113  * returns 0 on success
114  */
115 static int32_t
116 ulp_mapper_resource_ident_allocate(struct bnxt_ulp_context *ulp_ctx,
117                                    struct bnxt_ulp_mapper_data *mapper_data,
118                                    struct bnxt_ulp_glb_resource_info *glb_res)
119 {
120         struct tf_alloc_identifier_parms iparms = { 0 };
121         struct tf_free_identifier_parms fparms;
122         uint64_t regval;
123         struct tf *tfp;
124         int32_t rc = 0;
125
126         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO);
127         if (!tfp)
128                 return -EINVAL;
129
130         iparms.ident_type = glb_res->resource_type;
131         iparms.dir = glb_res->direction;
132
133         /* Allocate the Identifier using tf api */
134         rc = tf_alloc_identifier(tfp, &iparms);
135         if (rc) {
136                 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
137                             tf_dir_2_str(iparms.dir),
138                             iparms.ident_type);
139                 return rc;
140         }
141
142         /* entries are stored as big-endian format */
143         regval = tfp_cpu_to_be_64((uint64_t)iparms.id);
144         /*
145          * write to the mapper global resource
146          * Shared resources are never allocated through this method, so the
147          * shared flag is always false.
148          */
149         rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval, false);
150         if (rc) {
151                 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
152                 /* Free the identifier when update failed */
153                 fparms.dir = iparms.dir;
154                 fparms.ident_type = iparms.ident_type;
155                 fparms.id = iparms.id;
156                 tf_free_identifier(tfp, &fparms);
157                 return rc;
158         }
159         return rc;
160 }
161
162 /*
163  * Internal function to allocate index tbl resource and store it in mapper data.
164  *
165  * returns 0 on success
166  */
167 static int32_t
168 ulp_mapper_resource_index_tbl_alloc(struct bnxt_ulp_context *ulp_ctx,
169                                     struct bnxt_ulp_mapper_data *mapper_data,
170                                     struct bnxt_ulp_glb_resource_info *glb_res)
171 {
172         struct tf_alloc_tbl_entry_parms aparms = { 0 };
173         struct tf_free_tbl_entry_parms  free_parms = { 0 };
174         uint64_t regval;
175         struct tf *tfp;
176         uint32_t tbl_scope_id;
177         int32_t rc = 0;
178
179         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO);
180         if (!tfp)
181                 return -EINVAL;
182
183         /* Get the scope id */
184         rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &tbl_scope_id);
185         if (rc) {
186                 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
187                 return rc;
188         }
189
190         aparms.type = glb_res->resource_type;
191         aparms.dir = glb_res->direction;
192         aparms.search_enable = 0;
193         aparms.tbl_scope_id = tbl_scope_id;
194
195         /* Allocate the index tbl using tf api */
196         rc = tf_alloc_tbl_entry(tfp, &aparms);
197         if (rc) {
198                 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
199                             tf_dir_2_str(aparms.dir), aparms.type);
200                 return rc;
201         }
202
203         /* entries are stored as big-endian format */
204         regval = tfp_cpu_to_be_64((uint64_t)aparms.idx);
205         /*
206          * write to the mapper global resource
207          * Shared resources are never allocated through this method, so the
208          * shared flag is always false.
209          */
210         rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval, false);
211         if (rc) {
212                 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
213                 /* Free the identifier when update failed */
214                 free_parms.dir = aparms.dir;
215                 free_parms.type = aparms.type;
216                 free_parms.idx = aparms.idx;
217                 tf_free_tbl_entry(tfp, &free_parms);
218                 return rc;
219         }
220         return rc;
221 }
222
223 static int32_t
224 ulp_mapper_glb_field_tbl_get(struct bnxt_ulp_mapper_parms *parms,
225                              uint32_t operand,
226                              uint8_t *val)
227 {
228         uint32_t t_idx;
229
230         t_idx = parms->app_id << (BNXT_ULP_APP_ID_SHIFT +
231                                   BNXT_ULP_HDR_SIG_ID_SHIFT +
232                                   BNXT_ULP_GLB_FIELD_TBL_SHIFT);
233         t_idx += parms->class_tid << (BNXT_ULP_HDR_SIG_ID_SHIFT +
234                                       BNXT_ULP_GLB_FIELD_TBL_SHIFT);
235         t_idx += ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_HDR_SIG_ID) <<
236                 BNXT_ULP_GLB_FIELD_TBL_SHIFT;
237         t_idx += operand;
238
239         if (t_idx >= BNXT_ULP_GLB_FIELD_TBL_SIZE) {
240                 BNXT_TF_DBG(ERR, "Invalid hdr field index %x:%x:%x\n",
241                             parms->class_tid, t_idx, operand);
242                 *val = 0;
243                 return -EINVAL; /* error */
244         }
245         *val = ulp_glb_field_tbl[t_idx];
246         return 0;
247 }
248
249 /*
250  * Get the size of the action property for a given index.
251  *
252  * idx [in] The index for the action property
253  *
254  * returns the size of the action property.
255  */
256 static uint32_t
257 ulp_mapper_act_prop_size_get(uint32_t idx)
258 {
259         if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST)
260                 return 0;
261         return ulp_act_prop_map_table[idx];
262 }
263
264 static struct bnxt_ulp_mapper_cond_info *
265 ulp_mapper_tmpl_reject_list_get(struct bnxt_ulp_mapper_parms *mparms,
266                                 uint32_t tid,
267                                 uint32_t *num_tbls,
268                                 enum bnxt_ulp_cond_list_opc *opc)
269 {
270         uint32_t idx;
271         const struct bnxt_ulp_template_device_tbls *dev_tbls;
272
273         dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
274         *num_tbls = dev_tbls->tmpl_list[tid].reject_info.cond_nums;
275         *opc = dev_tbls->tmpl_list[tid].reject_info.cond_list_opcode;
276         idx = dev_tbls->tmpl_list[tid].reject_info.cond_start_idx;
277
278         return &dev_tbls->cond_list[idx];
279 }
280
281 static struct bnxt_ulp_mapper_cond_info *
282 ulp_mapper_tbl_execute_list_get(struct bnxt_ulp_mapper_parms *mparms,
283                                 struct bnxt_ulp_mapper_tbl_info *tbl,
284                                 uint32_t *num_tbls,
285                                 enum bnxt_ulp_cond_list_opc *opc)
286 {
287         uint32_t idx;
288         const struct bnxt_ulp_template_device_tbls *dev_tbls;
289
290         dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
291         *num_tbls = tbl->execute_info.cond_nums;
292         *opc = tbl->execute_info.cond_list_opcode;
293         idx = tbl->execute_info.cond_start_idx;
294
295         return &dev_tbls->cond_list[idx];
296 }
297
298 /*
299  * Get a list of classifier tables that implement the flow
300  * Gets a device dependent list of tables that implement the class template id
301  *
302  * mparms [in] The mappers parms with data related to the flow.
303  *
304  * tid [in] The template id that matches the flow
305  *
306  * num_tbls [out] The number of classifier tables in the returned array
307  *
308  * returns An array of classifier tables to implement the flow, or NULL on
309  * error
310  */
311 static struct bnxt_ulp_mapper_tbl_info *
312 ulp_mapper_tbl_list_get(struct bnxt_ulp_mapper_parms *mparms,
313                         uint32_t tid,
314                         uint32_t *num_tbls)
315 {
316         uint32_t idx;
317         const struct bnxt_ulp_template_device_tbls *dev_tbls;
318
319         dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
320
321         idx = dev_tbls->tmpl_list[tid].start_tbl_idx;
322         *num_tbls = dev_tbls->tmpl_list[tid].num_tbls;
323
324         return &dev_tbls->tbl_list[idx];
325 }
326
327 /*
328  * Get the list of key fields that implement the flow.
329  *
330  * mparms [in] The mapper parms with information about the flow
331  *
332  * tbl [in] A single table instance to get the key fields from
333  *
334  * num_flds [out] The number of key fields in the returned array
335  *
336  * Returns array of Key fields, or NULL on error.
337  */
338 static struct bnxt_ulp_mapper_key_info *
339 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_parms *mparms,
340                           struct bnxt_ulp_mapper_tbl_info *tbl,
341                           uint32_t *num_flds)
342 {
343         uint32_t idx;
344         const struct bnxt_ulp_template_device_tbls *dev_tbls;
345
346         dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
347         if (!dev_tbls->key_info_list) {
348                 *num_flds = 0;
349                 return NULL;
350         }
351
352         idx             = tbl->key_start_idx;
353         *num_flds       = tbl->key_num_fields;
354
355         return &dev_tbls->key_info_list[idx];
356 }
357
358 /*
359  * Get the list of data fields that implement the flow.
360  *
361  * mparms [in] The mapper parms with information about the flow
362  *
363  * tbl [in] A single table instance to get the data fields from
364  *
365  * num_flds [out] The number of data fields in the returned array.
366  *
367  * num_encap_flds [out] The number of encap fields in the returned array.
368  *
369  * Returns array of data fields, or NULL on error.
370  */
371 static struct bnxt_ulp_mapper_field_info *
372 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_parms *mparms,
373                              struct bnxt_ulp_mapper_tbl_info *tbl,
374                              uint32_t *num_flds,
375                              uint32_t *num_encap_flds)
376 {
377         uint32_t idx;
378         const struct bnxt_ulp_template_device_tbls *dev_tbls;
379
380         dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
381         if (!dev_tbls->result_field_list) {
382                 *num_flds = 0;
383                 *num_encap_flds = 0;
384                 return NULL;
385         }
386
387         idx             = tbl->result_start_idx;
388         *num_flds       = tbl->result_num_fields;
389         *num_encap_flds = tbl->encap_num_fields;
390
391         return &dev_tbls->result_field_list[idx];
392 }
393
394 /*
395  * Get the list of ident fields that implement the flow
396  *
397  * tbl [in] A single table instance to get the ident fields from
398  *
399  * num_flds [out] The number of ident fields in the returned array
400  *
401  * returns array of ident fields, or NULL on error
402  */
403 static struct bnxt_ulp_mapper_ident_info *
404 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_parms *mparms,
405                             struct bnxt_ulp_mapper_tbl_info *tbl,
406                             uint32_t *num_flds)
407 {
408         uint32_t idx;
409         const struct bnxt_ulp_template_device_tbls *dev_tbls;
410
411         dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
412         if (!dev_tbls->ident_list) {
413                 *num_flds = 0;
414                 return NULL;
415         }
416
417         idx = tbl->ident_start_idx;
418         *num_flds = tbl->ident_nums;
419
420         return &dev_tbls->ident_list[idx];
421 }
422
423 static inline int32_t
424 ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp,
425                            struct tf *tfp,
426                            struct ulp_flow_db_res_params *res)
427 {
428         struct tf_free_tcam_entry_parms fparms = {
429                 .dir            = res->direction,
430                 .tcam_tbl_type  = res->resource_type,
431                 .idx            = (uint16_t)res->resource_hndl
432         };
433
434         /* If HA is enabled, we may have to remap the TF Type */
435         if (bnxt_ulp_cntxt_ha_enabled(ulp)) {
436                 enum ulp_ha_mgr_region region;
437                 int32_t rc;
438
439                 switch (res->resource_type) {
440                 case TF_TCAM_TBL_TYPE_WC_TCAM_HIGH:
441                 case TF_TCAM_TBL_TYPE_WC_TCAM_LOW:
442                         rc = ulp_ha_mgr_region_get(ulp, &region);
443                         if (rc)
444                                 /* Log this, but assume region is correct */
445                                 BNXT_TF_DBG(ERR,
446                                             "Unable to get HA region (%d)\n",
447                                             rc);
448                         else
449                                 fparms.tcam_tbl_type =
450                                         (region == ULP_HA_REGION_LOW) ?
451                                         TF_TCAM_TBL_TYPE_WC_TCAM_LOW :
452                                         TF_TCAM_TBL_TYPE_WC_TCAM_HIGH;
453                         break;
454                 default:
455                         break;
456                 }
457         }
458         return tf_free_tcam_entry(tfp, &fparms);
459 }
460
461 static inline int32_t
462 ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp,
463                             struct tf *tfp,
464                             struct ulp_flow_db_res_params *res)
465 {
466         struct tf_free_tbl_entry_parms fparms = {
467                 .dir    = res->direction,
468                 .type   = res->resource_type,
469                 .idx    = (uint32_t)res->resource_hndl
470         };
471
472         /*
473          * Just get the table scope, it will be ignored if not necessary
474          * by the tf_free_tbl_entry
475          */
476         (void)bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
477
478         return tf_free_tbl_entry(tfp, &fparms);
479 }
480
481 static inline int32_t
482 ulp_mapper_em_entry_free(struct bnxt_ulp_context *ulp,
483                          struct tf *tfp,
484                          struct ulp_flow_db_res_params *res)
485 {
486         struct tf_delete_em_entry_parms fparms = { 0 };
487         int32_t rc;
488
489         fparms.dir              = res->direction;
490         fparms.flow_handle      = res->resource_hndl;
491
492         rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
493         if (rc) {
494                 BNXT_TF_DBG(ERR, "Failed to get table scope\n");
495                 return -EINVAL;
496         }
497
498         return tf_delete_em_entry(tfp, &fparms);
499 }
500
501 static inline int32_t
502 ulp_mapper_ident_free(struct bnxt_ulp_context *ulp __rte_unused,
503                       struct tf *tfp,
504                       struct ulp_flow_db_res_params *res)
505 {
506         struct tf_free_identifier_parms fparms = {
507                 .dir            = res->direction,
508                 .ident_type     = res->resource_type,
509                 .id             = (uint16_t)res->resource_hndl
510         };
511
512         return tf_free_identifier(tfp, &fparms);
513 }
514
515 static inline int32_t
516 ulp_mapper_mark_free(struct bnxt_ulp_context *ulp,
517                      struct ulp_flow_db_res_params *res)
518 {
519         return ulp_mark_db_mark_del(ulp,
520                                     res->resource_type,
521                                     res->resource_hndl);
522 }
523
524 static inline int32_t
525 ulp_mapper_parent_flow_free(struct bnxt_ulp_context *ulp,
526                             uint32_t parent_fid,
527                             struct ulp_flow_db_res_params *res)
528 {
529         uint32_t idx, child_fid = 0, parent_idx;
530         struct bnxt_ulp_flow_db *flow_db;
531
532         parent_idx = (uint32_t)res->resource_hndl;
533
534         /* check the validity of the parent fid */
535         if (ulp_flow_db_parent_flow_idx_get(ulp, parent_fid, &idx) ||
536             idx != parent_idx) {
537                 BNXT_TF_DBG(ERR, "invalid parent flow id %x\n", parent_fid);
538                 return -EINVAL;
539         }
540
541         /* Clear all the child flows parent index */
542         flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp);
543         while (!ulp_flow_db_parent_child_flow_next_entry_get(flow_db, idx,
544                                                              &child_fid)) {
545                 /* update the child flows resource handle */
546                 if (ulp_flow_db_child_flow_reset(ulp, BNXT_ULP_FDB_TYPE_REGULAR,
547                                                  child_fid)) {
548                         BNXT_TF_DBG(ERR, "failed to reset child flow %x\n",
549                                     child_fid);
550                         return -EINVAL;
551                 }
552         }
553
554         /* free the parent entry in the parent table flow */
555         if (ulp_flow_db_parent_flow_free(ulp, parent_fid)) {
556                 BNXT_TF_DBG(ERR, "failed to free parent flow %x\n", parent_fid);
557                 return -EINVAL;
558         }
559         return 0;
560 }
561
562 static inline int32_t
563 ulp_mapper_child_flow_free(struct bnxt_ulp_context *ulp,
564                            uint32_t child_fid,
565                            struct ulp_flow_db_res_params *res)
566 {
567         uint32_t parent_fid;
568
569         parent_fid = (uint32_t)res->resource_hndl;
570         if (!parent_fid)
571                 return 0; /* Already freed - orphan child*/
572
573         /* reset the child flow bitset*/
574         if (ulp_flow_db_parent_child_flow_set(ulp, parent_fid, child_fid, 0)) {
575                 BNXT_TF_DBG(ERR, "error in resetting child flow bitset %x:%x\n",
576                             parent_fid, child_fid);
577                 return -EINVAL;
578         }
579         return 0;
580 }
581
582 /*
583  * Process the flow database opcode alloc action.
584  * returns 0 on success
585  */
586 static int32_t
587 ulp_mapper_fdb_opc_alloc_rid(struct bnxt_ulp_mapper_parms *parms,
588                              struct bnxt_ulp_mapper_tbl_info *tbl)
589 {
590         uint32_t rid = 0;
591         uint64_t val64;
592         int32_t rc = 0;
593
594         /* allocate a new fid */
595         rc = ulp_flow_db_fid_alloc(parms->ulp_ctx,
596                                    BNXT_ULP_FDB_TYPE_RID,
597                                    0, &rid);
598         if (rc) {
599                 BNXT_TF_DBG(ERR,
600                             "Unable to allocate flow table entry\n");
601                 return -EINVAL;
602         }
603         /* Store the allocated fid in regfile*/
604         val64 = rid;
605         rc = ulp_regfile_write(parms->regfile, tbl->fdb_operand,
606                                tfp_cpu_to_be_64(val64));
607         if (rc) {
608                 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
609                             tbl->fdb_operand);
610                 ulp_flow_db_fid_free(parms->ulp_ctx,
611                                      BNXT_ULP_FDB_TYPE_RID, rid);
612                 return -EINVAL;
613         }
614         return 0;
615 }
616
617 /*
618  * Process the flow database opcode action.
619  * returns 0 on success.
620  */
621 static int32_t
622 ulp_mapper_fdb_opc_process(struct bnxt_ulp_mapper_parms *parms,
623                            struct bnxt_ulp_mapper_tbl_info *tbl,
624                            struct ulp_flow_db_res_params *fid_parms)
625 {
626         uint32_t push_fid;
627         uint64_t val64;
628         enum bnxt_ulp_fdb_type flow_type;
629         int32_t rc = 0;
630
631         switch (tbl->fdb_opcode) {
632         case BNXT_ULP_FDB_OPC_PUSH_FID:
633                 push_fid = parms->fid;
634                 flow_type = parms->flow_type;
635                 break;
636         case BNXT_ULP_FDB_OPC_PUSH_RID_REGFILE:
637                 /* get the fid from the regfile */
638                 rc = ulp_regfile_read(parms->regfile, tbl->fdb_operand,
639                                       &val64);
640                 if (!rc) {
641                         BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
642                                     tbl->fdb_operand);
643                         return -EINVAL;
644                 }
645                 /* Use the extracted fid to update the flow resource */
646                 push_fid = (uint32_t)tfp_be_to_cpu_64(val64);
647                 flow_type = BNXT_ULP_FDB_TYPE_RID;
648                 break;
649         default:
650                 return rc; /* Nothing to be done */
651         }
652
653         /* Add the resource to the flow database */
654         rc = ulp_flow_db_resource_add(parms->ulp_ctx, flow_type,
655                                       push_fid, fid_parms);
656         if (rc)
657                 BNXT_TF_DBG(ERR, "Failed to add res to flow %x rc = %d\n",
658                             push_fid, rc);
659         return rc;
660 }
661
662 /*
663  * Process the flow database opcode action.
664  * returns 0 on success.
665  */
666 static int32_t
667 ulp_mapper_priority_opc_process(struct bnxt_ulp_mapper_parms *parms,
668                                 struct bnxt_ulp_mapper_tbl_info *tbl,
669                                 uint32_t *priority)
670 {
671         int32_t rc = 0;
672
673         switch (tbl->pri_opcode) {
674         case BNXT_ULP_PRI_OPC_NOT_USED:
675                 *priority = 0;
676                 break;
677         case BNXT_ULP_PRI_OPC_CONST:
678                 *priority = tbl->pri_operand;
679                 break;
680         case BNXT_ULP_PRI_OPC_APP_PRI:
681                 *priority = parms->app_priority;
682                 break;
683         default:
684                 BNXT_TF_DBG(ERR, "Priority opcode not supported %d\n",
685                             tbl->pri_opcode);
686                 rc = -EINVAL;
687                 break;
688         }
689         return rc;
690 }
691
692 /*
693  * Process the identifier list in the given table.
694  * Extract the ident from the table entry and
695  * write it to the reg file.
696  * returns 0 on success.
697  */
698 static int32_t
699 ulp_mapper_tbl_ident_scan_ext(struct bnxt_ulp_mapper_parms *parms,
700                               struct bnxt_ulp_mapper_tbl_info *tbl,
701                               uint8_t *byte_data,
702                               uint32_t byte_data_size,
703                               enum bnxt_ulp_byte_order byte_order)
704 {
705         struct bnxt_ulp_mapper_ident_info *idents;
706         uint32_t i, num_idents = 0;
707         uint64_t val64;
708
709         /* validate the null arguments */
710         if (!byte_data) {
711                 BNXT_TF_DBG(ERR, "invalid argument\n");
712                 return -EINVAL;
713         }
714
715         /* Get the ident list and process each one */
716         idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
717
718         for (i = 0; i < num_idents; i++) {
719                 /* check the size of the buffer for validation */
720                 if ((idents[i].ident_bit_pos + idents[i].ident_bit_size) >
721                     ULP_BYTE_2_BITS(byte_data_size) ||
722                     idents[i].ident_bit_size > ULP_BYTE_2_BITS(sizeof(val64))) {
723                         BNXT_TF_DBG(ERR, "invalid offset or length %x:%x:%x\n",
724                                     idents[i].ident_bit_pos,
725                                     idents[i].ident_bit_size,
726                                     byte_data_size);
727                         return -EINVAL;
728                 }
729                 val64 = 0;
730                 if (byte_order == BNXT_ULP_BYTE_ORDER_LE)
731                         ulp_bs_pull_lsb(byte_data, (uint8_t *)&val64,
732                                         sizeof(val64),
733                                         idents[i].ident_bit_pos,
734                                         idents[i].ident_bit_size);
735                 else
736                         ulp_bs_pull_msb(byte_data, (uint8_t *)&val64,
737                                         idents[i].ident_bit_pos,
738                                         idents[i].ident_bit_size);
739
740                 /* Write it to the regfile, val64 is already in big-endian*/
741                 if (ulp_regfile_write(parms->regfile,
742                                       idents[i].regfile_idx, val64)) {
743                         BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
744                                     idents[i].regfile_idx);
745                         return -EINVAL;
746                 }
747         }
748         return 0;
749 }
750
751 /*
752  * Process the identifier instruction and either store it in the flow database
753  * or return it in the val (if not NULL) on success.  If val is NULL, the
754  * identifier is to be stored in the flow database.
755  */
756 static int32_t
757 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms,
758                          struct bnxt_ulp_mapper_tbl_info *tbl,
759                          struct bnxt_ulp_mapper_ident_info *ident,
760                          uint16_t *val)
761 {
762         struct ulp_flow_db_res_params   fid_parms;
763         uint64_t id = 0;
764         int32_t idx;
765         struct tf_alloc_identifier_parms iparms = { 0 };
766         struct tf_free_identifier_parms free_parms = { 0 };
767         struct tf *tfp;
768         int rc;
769
770         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
771         if (!tfp) {
772                 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
773                 return -EINVAL;
774         }
775
776         idx = ident->regfile_idx;
777
778         iparms.ident_type = ident->ident_type;
779         iparms.dir = tbl->direction;
780
781         rc = tf_alloc_identifier(tfp, &iparms);
782         if (rc) {
783                 BNXT_TF_DBG(ERR, "Alloc ident %s:%s failed.\n",
784                             tf_dir_2_str(iparms.dir),
785                             tf_ident_2_str(iparms.ident_type));
786                 return rc;
787         }
788
789         id = (uint64_t)tfp_cpu_to_be_64(iparms.id);
790         if (ulp_regfile_write(parms->regfile, idx, id)) {
791                 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
792                 rc = -EINVAL;
793                 /* Need to free the identifier, so goto error */
794                 goto error;
795         }
796
797         /* Link the resource to the flow in the flow db */
798         if (!val) {
799                 memset(&fid_parms, 0, sizeof(fid_parms));
800                 fid_parms.direction             = tbl->direction;
801                 fid_parms.resource_func = ident->resource_func;
802                 fid_parms.resource_type = ident->ident_type;
803                 fid_parms.resource_hndl = iparms.id;
804                 fid_parms.critical_resource = tbl->critical_resource;
805                 ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
806
807                 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
808                 if (rc) {
809                         BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
810                                     rc);
811                         /* Need to free the identifier, so goto error */
812                         goto error;
813                 }
814         } else {
815                 *val = iparms.id;
816         }
817         return 0;
818
819 error:
820         /* Need to free the identifier */
821         free_parms.dir          = tbl->direction;
822         free_parms.ident_type   = ident->ident_type;
823         free_parms.id           = iparms.id;
824
825         (void)tf_free_identifier(tfp, &free_parms);
826
827         BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n",
828                     ident->description,
829                     tf_dir_2_str(tbl->direction));
830         return rc;
831 }
832
833 /*
834  * Process the identifier instruction and extract it from result blob.
835  * Increment the identifier reference count and store it in the flow database.
836  */
837 static int32_t
838 ulp_mapper_ident_extract(struct bnxt_ulp_mapper_parms *parms,
839                          struct bnxt_ulp_mapper_tbl_info *tbl,
840                          struct bnxt_ulp_mapper_ident_info *ident,
841                          struct ulp_blob *res_blob)
842 {
843         struct ulp_flow_db_res_params   fid_parms;
844         uint64_t id = 0;
845         uint32_t idx = 0;
846         struct tf_search_identifier_parms sparms = { 0 };
847         struct tf_free_identifier_parms free_parms = { 0 };
848         struct tf *tfp;
849         int rc;
850
851         /* Get the tfp from ulp context */
852         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
853         if (!tfp) {
854                 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
855                 return -EINVAL;
856         }
857
858         /* Extract the index from the result blob */
859         rc = ulp_blob_pull(res_blob, (uint8_t *)&idx, sizeof(idx),
860                            ident->ident_bit_pos, ident->ident_bit_size);
861         if (rc) {
862                 BNXT_TF_DBG(ERR, "Failed to extract identifier from blob\n");
863                 return -EIO;
864         }
865
866         /* populate the search params and search identifier shadow table */
867         sparms.ident_type = ident->ident_type;
868         sparms.dir = tbl->direction;
869         /* convert the idx into cpu format */
870         sparms.search_id = tfp_be_to_cpu_32(idx);
871
872         /* Search identifier also increase the reference count */
873         rc = tf_search_identifier(tfp, &sparms);
874         if (rc) {
875                 BNXT_TF_DBG(ERR, "Search ident %s:%s:%x failed.\n",
876                             tf_dir_2_str(sparms.dir),
877                             tf_ident_2_str(sparms.ident_type),
878                             sparms.search_id);
879                 return rc;
880         }
881
882         /* Write it to the regfile */
883         id = (uint64_t)tfp_cpu_to_be_64(sparms.search_id);
884         if (ulp_regfile_write(parms->regfile, ident->regfile_idx, id)) {
885                 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
886                 rc = -EINVAL;
887                 /* Need to free the identifier, so goto error */
888                 goto error;
889         }
890
891         /* Link the resource to the flow in the flow db */
892         memset(&fid_parms, 0, sizeof(fid_parms));
893         fid_parms.direction = tbl->direction;
894         fid_parms.resource_func = ident->resource_func;
895         fid_parms.resource_type = ident->ident_type;
896         fid_parms.resource_hndl = sparms.search_id;
897         fid_parms.critical_resource = tbl->critical_resource;
898         ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
899
900         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
901         if (rc) {
902                 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
903                             rc);
904                 /* Need to free the identifier, so goto error */
905                 goto error;
906         }
907
908         return 0;
909
910 error:
911         /* Need to free the identifier */
912         free_parms.dir = tbl->direction;
913         free_parms.ident_type = ident->ident_type;
914         free_parms.id = sparms.search_id;
915         (void)tf_free_identifier(tfp, &free_parms);
916         BNXT_TF_DBG(ERR, "Ident extract failed for %s:%s:%x\n",
917                     ident->description,
918                     tf_dir_2_str(tbl->direction), sparms.search_id);
919         return rc;
920 }
921
922 static int32_t
923 ulp_mapper_field_port_db_process(struct bnxt_ulp_mapper_parms *parms,
924                                  uint32_t port_id,
925                                  uint16_t val16,
926                                  uint8_t **val)
927 {
928         enum bnxt_ulp_port_table port_data = val16;
929
930         switch (port_data) {
931         case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_MAC:
932                 if (ulp_port_db_parent_mac_addr_get(parms->ulp_ctx, port_id,
933                                                     val)) {
934                         BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
935                         return -EINVAL;
936                 }
937                 break;
938         case BNXT_ULP_PORT_TABLE_DRV_FUNC_MAC:
939                 if (ulp_port_db_drv_mac_addr_get(parms->ulp_ctx, port_id,
940                                                  val)) {
941                         BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
942                         return -EINVAL;
943                 }
944                 break;
945         case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_VNIC:
946                 if (ulp_port_db_parent_vnic_get(parms->ulp_ctx, port_id,
947                                                 val)) {
948                         BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
949                         return -EINVAL;
950                 }
951                 break;
952         default:
953                 BNXT_TF_DBG(ERR, "Invalid port_data %d\n", port_data);
954                 return -EINVAL;
955         }
956         return 0;
957 }
958
959 static int32_t
960 ulp_mapper_field_src_process(struct bnxt_ulp_mapper_parms *parms,
961                              enum bnxt_ulp_field_src field_src,
962                              uint8_t *field_opr,
963                              enum tf_dir dir,
964                              uint8_t is_key,
965                              uint32_t bitlen,
966                              uint8_t **val,
967                              uint32_t *val_len,
968                              uint64_t *value)
969 {
970         struct bnxt_ulp_mapper_data *m;
971         uint8_t bit;
972         uint32_t port_id, val_size, field_size;
973         uint16_t idx, size_idx, offset;
974         uint32_t bytelen = ULP_BITS_2_BYTE(bitlen);
975         uint8_t *buffer;
976         uint64_t lregval;
977         bool shared;
978
979         *val_len = bitlen;
980         *value = 0;
981         /* Perform the action */
982         switch (field_src) {
983         case BNXT_ULP_FIELD_SRC_ZERO:
984                 *val = mapper_fld_zeros;
985                 break;
986         case BNXT_ULP_FIELD_SRC_CONST:
987                 *val = field_opr;
988                 break;
989         case BNXT_ULP_FIELD_SRC_ONES:
990                 *val = mapper_fld_ones;
991                 *value = 1;
992                 break;
993         case BNXT_ULP_FIELD_SRC_CF:
994                 if (!ulp_operand_read(field_opr,
995                                       (uint8_t *)&idx, sizeof(uint16_t))) {
996                         BNXT_TF_DBG(ERR, "CF operand read failed\n");
997                         return -EINVAL;
998                 }
999                 idx = tfp_be_to_cpu_16(idx);
1000                 if (idx >= BNXT_ULP_CF_IDX_LAST || bytelen > sizeof(uint64_t)) {
1001                         BNXT_TF_DBG(ERR, "comp field [%d] read oob %d\n", idx,
1002                                     bytelen);
1003                         return -EINVAL;
1004                 }
1005                 buffer = (uint8_t *)&parms->comp_fld[idx];
1006                 *val = &buffer[sizeof(uint64_t) - bytelen];
1007                 *value = ULP_COMP_FLD_IDX_RD(parms, idx);
1008                 break;
1009         case BNXT_ULP_FIELD_SRC_RF:
1010                 if (!ulp_operand_read(field_opr,
1011                                       (uint8_t *)&idx, sizeof(uint16_t))) {
1012                         BNXT_TF_DBG(ERR, "RF operand read failed\n");
1013                         return -EINVAL;
1014                 }
1015
1016                 idx = tfp_be_to_cpu_16(idx);
1017                 /* Uninitialized regfile entries return 0 */
1018                 if (!ulp_regfile_read(parms->regfile, idx, &lregval) ||
1019                     sizeof(uint64_t) < bytelen) {
1020                         BNXT_TF_DBG(ERR, "regfile[%d] read oob %u\n", idx,
1021                                     bytelen);
1022                         return -EINVAL;
1023                 }
1024                 buffer = (uint8_t *)&parms->regfile->entry[idx].data;
1025                 *val = &buffer[sizeof(uint64_t) - bytelen];
1026                 *value = tfp_be_to_cpu_64(lregval);
1027                 break;
1028         case BNXT_ULP_FIELD_SRC_ACT_PROP:
1029                 if (!ulp_operand_read(field_opr,
1030                                       (uint8_t *)&idx, sizeof(uint16_t))) {
1031                         BNXT_TF_DBG(ERR, "Action operand read failed\n");
1032                         return -EINVAL;
1033                 }
1034                 idx = tfp_be_to_cpu_16(idx);
1035                 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1036                         BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", idx);
1037                         return -EINVAL;
1038                 }
1039                 buffer = &parms->act_prop->act_details[idx];
1040                 field_size = ulp_mapper_act_prop_size_get(idx);
1041                 if (bytelen > field_size) {
1042                         BNXT_TF_DBG(ERR, "act_prop[%d] field size small %u\n",
1043                                     idx, field_size);
1044                         return -EINVAL;
1045                 }
1046                 *val = &buffer[field_size - bytelen];
1047                 break;
1048         case BNXT_ULP_FIELD_SRC_ACT_PROP_SZ:
1049                 if (!ulp_operand_read(field_opr,
1050                                       (uint8_t *)&idx, sizeof(uint16_t))) {
1051                         BNXT_TF_DBG(ERR, "Action sz operand read failed\n");
1052                         return -EINVAL;
1053                 }
1054                 idx = tfp_be_to_cpu_16(idx);
1055
1056                 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1057                         BNXT_TF_DBG(ERR, "act_prop_sz[%d] oob\n", idx);
1058                         return -EINVAL;
1059                 }
1060                 *val = &parms->act_prop->act_details[idx];
1061
1062                 /* get the size index next */
1063                 if (!ulp_operand_read(&field_opr[sizeof(uint16_t)],
1064                                       (uint8_t *)&size_idx, sizeof(uint16_t))) {
1065                         BNXT_TF_DBG(ERR, "Action sz operand read failed\n");
1066                         return -EINVAL;
1067                 }
1068                 size_idx = tfp_be_to_cpu_16(size_idx);
1069                 if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1070                         BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx);
1071                         return -EINVAL;
1072                 }
1073                 memcpy(&val_size, &parms->act_prop->act_details[size_idx],
1074                        sizeof(uint32_t));
1075                 val_size = tfp_be_to_cpu_32(val_size);
1076                 *val_len = ULP_BYTE_2_BITS(val_size);
1077                 break;
1078         case BNXT_ULP_FIELD_SRC_GLB_RF:
1079                 if (!ulp_operand_read(field_opr,
1080                                       (uint8_t *)&idx, sizeof(uint16_t))) {
1081                         BNXT_TF_DBG(ERR, "Global regfile read failed\n");
1082                         return -EINVAL;
1083                 }
1084                 idx = tfp_be_to_cpu_16(idx);
1085                 if (ulp_mapper_glb_resource_read(parms->mapper_data,
1086                                                  dir, idx, &lregval, &shared) ||
1087                     sizeof(uint64_t) < bytelen) {
1088                         BNXT_TF_DBG(ERR, "Global regfile[%d] read failed %u\n",
1089                                     idx, bytelen);
1090                         return -EINVAL;
1091                 }
1092                 m = parms->mapper_data;
1093                 buffer = (uint8_t *)&m->glb_res_tbl[dir][idx].resource_hndl;
1094                 *val = &buffer[sizeof(uint64_t) - bytelen];
1095                 *value = tfp_be_to_cpu_64(lregval);
1096                 break;
1097         case BNXT_ULP_FIELD_SRC_HF:
1098         case BNXT_ULP_FIELD_SRC_SUB_HF:
1099                 if (!ulp_operand_read(field_opr,
1100                                       (uint8_t *)&idx, sizeof(uint16_t))) {
1101                         BNXT_TF_DBG(ERR, "Header field read failed\n");
1102                         return -EINVAL;
1103                 }
1104                 idx = tfp_be_to_cpu_16(idx);
1105                 /* get the index from the global field list */
1106                 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1107                         BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1108                                     idx);
1109                         return -EINVAL;
1110                 }
1111                 if (is_key)
1112                         buffer = parms->hdr_field[bit].spec;
1113                 else
1114                         buffer = parms->hdr_field[bit].mask;
1115
1116                 field_size = parms->hdr_field[bit].size;
1117                 if (bytelen > field_size) {
1118                         BNXT_TF_DBG(ERR, "Hdr field[%d] size small %u\n",
1119                                     bit, field_size);
1120                         return -EINVAL;
1121                 }
1122                 if (field_src == BNXT_ULP_FIELD_SRC_HF) {
1123                         *val = &buffer[field_size - bytelen];
1124                 } else {
1125                         /* get the offset next */
1126                         if (!ulp_operand_read(&field_opr[sizeof(uint16_t)],
1127                                               (uint8_t *)&offset,
1128                                               sizeof(uint16_t))) {
1129                                 BNXT_TF_DBG(ERR, "Hdr fld size read failed\n");
1130                                 return -EINVAL;
1131                         }
1132                         offset = tfp_be_to_cpu_16(offset);
1133                         offset = ULP_BITS_2_BYTE_NR(offset);
1134                         if ((offset + bytelen) > field_size) {
1135                                 BNXT_TF_DBG(ERR, "Hdr field[%d] oob\n", bit);
1136                                 return -EINVAL;
1137                         }
1138                         *val = &buffer[offset];
1139                 }
1140                 break;
1141         case BNXT_ULP_FIELD_SRC_HDR_BIT:
1142                 if (!ulp_operand_read(field_opr,
1143                                       (uint8_t *)&lregval, sizeof(uint64_t))) {
1144                         BNXT_TF_DBG(ERR, "Header bit read failed\n");
1145                         return -EINVAL;
1146                 }
1147                 lregval = tfp_be_to_cpu_64(lregval);
1148                 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, lregval)) {
1149                         *val = mapper_fld_one;
1150                         *value = 1;
1151                 } else {
1152                         *val = mapper_fld_zeros;
1153                 }
1154                 break;
1155         case BNXT_ULP_FIELD_SRC_ACT_BIT:
1156                 if (!ulp_operand_read(field_opr,
1157                                       (uint8_t *)&lregval, sizeof(uint64_t))) {
1158                         BNXT_TF_DBG(ERR, "Action bit read failed\n");
1159                         return -EINVAL;
1160                 }
1161                 lregval = tfp_be_to_cpu_64(lregval);
1162                 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, lregval)) {
1163                         *val = mapper_fld_one;
1164                         *value = 1;
1165                 } else {
1166                         *val = mapper_fld_zeros;
1167                 }
1168                 break;
1169         case BNXT_ULP_FIELD_SRC_FIELD_BIT:
1170                 if (!ulp_operand_read(field_opr,
1171                                       (uint8_t *)&idx, sizeof(uint16_t))) {
1172                         BNXT_TF_DBG(ERR, "Field bit read failed\n");
1173                         return -EINVAL;
1174                 }
1175                 idx = tfp_be_to_cpu_16(idx);
1176                 /* get the index from the global field list */
1177                 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1178                         BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1179                                     idx);
1180                         return -EINVAL;
1181                 }
1182                 if (ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit)) {
1183                         *val = mapper_fld_one;
1184                         *value = 1;
1185                 } else {
1186                         *val = mapper_fld_zeros;
1187                 }
1188                 break;
1189         case BNXT_ULP_FIELD_SRC_PORT_TABLE:
1190                 /* The port id is present in the comp field list */
1191                 port_id = ULP_COMP_FLD_IDX_RD(parms,
1192                                               BNXT_ULP_CF_IDX_DEV_PORT_ID);
1193                 /* get the port table enum  */
1194                 if (!ulp_operand_read(field_opr,
1195                                       (uint8_t *)&idx, sizeof(uint16_t))) {
1196                         BNXT_TF_DBG(ERR, "Port table enum read failed\n");
1197                         return -EINVAL;
1198                 }
1199                 idx = tfp_be_to_cpu_16(idx);
1200                 if (ulp_mapper_field_port_db_process(parms, port_id, idx,
1201                                                      val)) {
1202                         BNXT_TF_DBG(ERR, "field port table failed\n");
1203                         return -EINVAL;
1204                 }
1205         case BNXT_ULP_FIELD_SRC_SKIP:
1206                 /* do nothing */
1207                 break;
1208         case BNXT_ULP_FIELD_SRC_REJECT:
1209                 return -EINVAL;
1210         default:
1211                 BNXT_TF_DBG(ERR, "invalid field opcode 0x%x\n", field_src);
1212                 return -EINVAL;
1213         }
1214         return 0;
1215 }
1216
1217 static int32_t ulp_mapper_field_buffer_eval(uint8_t *buffer, uint32_t bitlen,
1218                                             uint64_t *output)
1219 {
1220         uint16_t val_16;
1221         uint32_t val_32;
1222         uint64_t val_64;
1223         uint32_t bytelen;
1224
1225         bytelen = ULP_BITS_2_BYTE(bitlen);
1226         if (bytelen == sizeof(uint8_t)) {
1227                 *output = *((uint8_t *)buffer);
1228         } else if (bytelen == sizeof(uint16_t)) {
1229                 val_16 = *((uint16_t *)buffer);
1230                 *output =  tfp_be_to_cpu_16(val_16);
1231         } else if (bytelen == sizeof(uint32_t)) {
1232                 val_32 = *((uint32_t *)buffer);
1233                 *output =  tfp_be_to_cpu_32(val_32);
1234         } else if (bytelen == sizeof(val_64)) {
1235                 val_64 = *((uint64_t *)buffer);
1236                 *output =  tfp_be_to_cpu_64(val_64);
1237         } else {
1238                 *output = 0;
1239                 return -EINVAL;
1240         }
1241         return 0;
1242 }
1243
1244 static int32_t ulp_mapper_field_blob_write(enum bnxt_ulp_field_src fld_src,
1245                                            struct ulp_blob *blob,
1246                                            uint8_t *val,
1247                                            uint32_t val_len,
1248                                            uint8_t **out_val)
1249 {
1250         if (fld_src == BNXT_ULP_FIELD_SRC_ZERO) {
1251                 if (ulp_blob_pad_push(blob, val_len) < 0) {
1252                         BNXT_TF_DBG(ERR, "too large for blob\n");
1253                         return -EINVAL;
1254                 }
1255         } else if (fld_src == BNXT_ULP_FIELD_SRC_ACT_PROP_SZ) {
1256                 if (ulp_blob_push_encap(blob, val, val_len) < 0) {
1257                         BNXT_TF_DBG(ERR, "encap blob push failed\n");
1258                         return -EINVAL;
1259                 }
1260         } else {
1261                 if (!ulp_blob_push(blob, val, val_len)) {
1262                         BNXT_TF_DBG(ERR, "push of val1 failed\n");
1263                         return -EINVAL;
1264                 }
1265         }
1266         *out_val = val;
1267         return 0;
1268 }
1269
1270 static int32_t
1271 ulp_mapper_field_opc_process(struct bnxt_ulp_mapper_parms *parms,
1272                              enum tf_dir dir,
1273                              struct bnxt_ulp_mapper_field_info *fld,
1274                              struct ulp_blob *blob,
1275                              uint8_t is_key,
1276                              const char *name)
1277 {
1278         uint16_t write_idx = blob->write_idx;
1279         uint8_t *val = NULL, *val1, *val2, *val3;
1280         uint32_t val_len = 0, val1_len = 0, val2_len = 0, val3_len = 0;
1281         uint8_t process_src1 = 0, process_src2 = 0, process_src3 = 0;
1282         uint8_t eval_src1 = 0, eval_src2 = 0, eval_src3 = 0;
1283         uint64_t val_int = 0, val1_int = 0, val2_int = 0, val3_int = 0;
1284         uint64_t value1 = 0, value2 = 0, value3 = 0;
1285         int32_t rc = 0;
1286
1287         /* prepare the field source and values */
1288         switch (fld->field_opc) {
1289         case BNXT_ULP_FIELD_OPC_SRC1:
1290                 process_src1 = 1;
1291                 break;
1292         case BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3:
1293                 process_src1 = 1;
1294                 break;
1295         case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2_OR_SRC3:
1296         case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2_OR_SRC3:
1297                 process_src3 = 1;
1298                 eval_src3 = 1;
1299                 process_src1 = 1;
1300                 process_src2 = 1;
1301                 eval_src1 = 1;
1302                 eval_src2 = 1;
1303                 break;
1304         case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2:
1305         case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2:
1306         case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2_POST:
1307         case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2_POST:
1308         case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2:
1309         case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2:
1310                 process_src1 = 1;
1311                 process_src2 = 1;
1312                 eval_src1 = 1;
1313                 eval_src2 = 1;
1314                 break;
1315         default:
1316                 break;
1317         }
1318
1319         /* process the src1 opcode  */
1320         if (process_src1) {
1321                 if (ulp_mapper_field_src_process(parms, fld->field_src1,
1322                                                  fld->field_opr1, dir, is_key,
1323                                                  fld->field_bit_size, &val1,
1324                                                  &val1_len, &value1)) {
1325                         BNXT_TF_DBG(ERR, "fld src1 process failed\n");
1326                         goto error;
1327                 }
1328                 if (eval_src1) {
1329                         if (ulp_mapper_field_buffer_eval(val1, val1_len,
1330                                                          &val1_int)) {
1331                                 BNXT_TF_DBG(ERR, "fld src1 eval failed\n");
1332                                 goto error;
1333                         }
1334                 }
1335         }
1336
1337         /* for "if then clause" set the correct process  */
1338         if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3) {
1339                 if (value1)
1340                         process_src2 = 1;
1341                 else
1342                         process_src3 = 1;
1343         }
1344
1345         /* process src2 opcode */
1346         if (process_src2) {
1347                 if (ulp_mapper_field_src_process(parms, fld->field_src2,
1348                                                  fld->field_opr2, dir, is_key,
1349                                                  fld->field_bit_size, &val2,
1350                                                  &val2_len, &value2)) {
1351                         BNXT_TF_DBG(ERR, "fld src2 process failed\n");
1352                         goto error;
1353                 }
1354                 if (eval_src2) {
1355                         if (ulp_mapper_field_buffer_eval(val2, val2_len,
1356                                                          &val2_int)) {
1357                                 BNXT_TF_DBG(ERR, "fld src2 eval failed\n");
1358                                 goto error;
1359                         }
1360                 }
1361         }
1362
1363         /* process src3 opcode */
1364         if (process_src3) {
1365                 if (ulp_mapper_field_src_process(parms, fld->field_src3,
1366                                                  fld->field_opr3, dir, is_key,
1367                                                  fld->field_bit_size, &val3,
1368                                                  &val3_len, &value3)) {
1369                         BNXT_TF_DBG(ERR, "fld src3 process failed\n");
1370                         goto error;
1371                 }
1372                 if (eval_src3) {
1373                         if (ulp_mapper_field_buffer_eval(val3, val3_len,
1374                                                          &val3_int)) {
1375                                 BNXT_TF_DBG(ERR, "fld src3 eval failed\n");
1376                                 goto error;
1377                         }
1378                 }
1379         }
1380
1381         val_len = fld->field_bit_size;
1382         /* process the field opcodes */
1383         switch (fld->field_opc) {
1384         case BNXT_ULP_FIELD_OPC_SRC1:
1385                 rc = ulp_mapper_field_blob_write(fld->field_src1,
1386                                                  blob, val1, val1_len, &val);
1387                 val_len = val1_len;
1388                 break;
1389         case BNXT_ULP_FIELD_OPC_SRC1_THEN_SRC2_ELSE_SRC3:
1390                 if (value1) {
1391                         rc = ulp_mapper_field_blob_write(fld->field_src2, blob,
1392                                                          val2, val2_len, &val);
1393                         val_len = val2_len;
1394                 } else {
1395                         rc = ulp_mapper_field_blob_write(fld->field_src3, blob,
1396                                                          val3, val3_len, &val);
1397                         val_len = val3_len;
1398                 }
1399                 break;
1400         case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2:
1401         case BNXT_ULP_FIELD_OPC_SRC1_PLUS_SRC2_POST:
1402                 val_int = val1_int + val2_int;
1403                 val_int = tfp_cpu_to_be_64(val_int);
1404                 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1405                 if (!val)
1406                         rc = -EINVAL;
1407                 break;
1408         case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2:
1409         case BNXT_ULP_FIELD_OPC_SRC1_MINUS_SRC2_POST:
1410                 val_int = val1_int - val2_int;
1411                 val_int = tfp_cpu_to_be_64(val_int);
1412                 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1413                 if (!val)
1414                         rc = -EINVAL;
1415                 break;
1416         case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2:
1417                 val_int = val1_int | val2_int;
1418                 val_int = tfp_cpu_to_be_64(val_int);
1419                 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1420                 if (!val)
1421                         rc = -EINVAL;
1422                 break;
1423         case BNXT_ULP_FIELD_OPC_SRC1_OR_SRC2_OR_SRC3:
1424                 val_int = val1_int | val2_int | val3_int;
1425                 val_int = tfp_cpu_to_be_64(val_int);
1426                 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1427                 if (!val)
1428                         rc = -EINVAL;
1429                 break;
1430         case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2:
1431                 val_int = val1_int & val2_int;
1432                 val_int = tfp_cpu_to_be_64(val_int);
1433                 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1434                 if (!val)
1435                         rc = -EINVAL;
1436                 break;
1437         case BNXT_ULP_FIELD_OPC_SRC1_AND_SRC2_OR_SRC3:
1438                 val_int = val1_int & (val2_int | val3_int);
1439                 val_int = tfp_cpu_to_be_64(val_int);
1440                 val = ulp_blob_push_64(blob, &val_int, fld->field_bit_size);
1441                 if (!val)
1442                         rc = -EINVAL;
1443                 break;
1444         case BNXT_ULP_FIELD_OPC_SKIP:
1445                 break;
1446         default:
1447                 BNXT_TF_DBG(ERR, "Invalid fld opcode %u\n", fld->field_opc);
1448                 rc = -EINVAL;
1449                 break;
1450         }
1451
1452         return rc;
1453 error:
1454         BNXT_TF_DBG(ERR, "Error in %s:%s process %u:%u\n", name,
1455                     fld->description, (val) ? write_idx : 0, val_len);
1456         return -EINVAL;
1457 }
1458
1459 /*
1460  * Result table process and fill the result blob.
1461  * data [out] - the result blob data
1462  */
1463 static int32_t
1464 ulp_mapper_tbl_result_build(struct bnxt_ulp_mapper_parms *parms,
1465                             struct bnxt_ulp_mapper_tbl_info *tbl,
1466                             struct ulp_blob *data,
1467                             const char *name)
1468 {
1469         struct bnxt_ulp_mapper_field_info *dflds;
1470         uint32_t i, num_flds = 0, encap_flds = 0;
1471         int32_t rc = 0;
1472
1473         /* Get the result field list */
1474         dflds = ulp_mapper_result_fields_get(parms, tbl, &num_flds,
1475                                              &encap_flds);
1476
1477         /* validate the result field list counts */
1478         if ((tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1479              (!num_flds && !encap_flds)) || !dflds ||
1480             (tbl->resource_func != BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1481                 (!num_flds || encap_flds))) {
1482                 BNXT_TF_DBG(ERR, "Failed to get data fields %x:%x\n",
1483                             num_flds, encap_flds);
1484                 return -EINVAL;
1485         }
1486
1487         /* process the result fields, loop through them */
1488         for (i = 0; i < (num_flds + encap_flds); i++) {
1489                 /* set the swap index if encap swap bit is enabled */
1490                 if (parms->device_params->encap_byte_swap && encap_flds &&
1491                     i == num_flds)
1492                         ulp_blob_encap_swap_idx_set(data);
1493
1494                 /* Process the result fields */
1495                 rc = ulp_mapper_field_opc_process(parms, tbl->direction,
1496                                                   &dflds[i], data, 0, name);
1497                 if (rc) {
1498                         BNXT_TF_DBG(ERR, "data field failed\n");
1499                         return rc;
1500                 }
1501         }
1502
1503         /* if encap bit swap is enabled perform the bit swap */
1504         if (parms->device_params->encap_byte_swap && encap_flds)
1505                 ulp_blob_perform_encap_swap(data);
1506
1507         return rc;
1508 }
1509
1510 static int32_t
1511 ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms,
1512                              struct bnxt_ulp_mapper_tbl_info *tbl,
1513                              uint64_t flow_id)
1514 {
1515         struct ulp_flow_db_res_params fid_parms;
1516         uint32_t mark, gfid, mark_flag;
1517         enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1518         int32_t rc = 0;
1519
1520         if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1521             !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1522              ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1523                               BNXT_ULP_ACT_BIT_MARK)))
1524                 return rc; /* no need to perform gfid process */
1525
1526         /* Get the mark id details from action property */
1527         memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1528                sizeof(mark));
1529         mark = tfp_be_to_cpu_32(mark);
1530
1531         TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid);
1532         mark_flag  = BNXT_ULP_MARK_GLOBAL_HW_FID;
1533
1534         rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1535                                   gfid, mark);
1536         if (rc) {
1537                 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1538                 return rc;
1539         }
1540         fid_parms.direction = tbl->direction;
1541         fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1542         fid_parms.critical_resource = tbl->critical_resource;
1543         fid_parms.resource_type = mark_flag;
1544         fid_parms.resource_hndl = gfid;
1545         ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
1546
1547         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1548         if (rc)
1549                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1550         return rc;
1551 }
1552
1553 static int32_t
1554 ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms,
1555                                 struct bnxt_ulp_mapper_tbl_info *tbl)
1556 {
1557         struct ulp_flow_db_res_params fid_parms;
1558         uint32_t act_idx, mark, mark_flag;
1559         uint64_t val64;
1560         enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1561         int32_t rc = 0;
1562
1563         if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1564             !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1565              ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1566                               BNXT_ULP_ACT_BIT_MARK)))
1567                 return rc; /* no need to perform mark action process */
1568
1569         /* Get the mark id details from action property */
1570         memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1571                sizeof(mark));
1572         mark = tfp_be_to_cpu_32(mark);
1573
1574         if (!ulp_regfile_read(parms->regfile,
1575                               BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1576                               &val64)) {
1577                 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1578                 return -EINVAL;
1579         }
1580         act_idx = tfp_be_to_cpu_64(val64);
1581         mark_flag  = BNXT_ULP_MARK_LOCAL_HW_FID;
1582         rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1583                                   act_idx, mark);
1584         if (rc) {
1585                 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1586                 return rc;
1587         }
1588         fid_parms.direction = tbl->direction;
1589         fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1590         fid_parms.critical_resource = tbl->critical_resource;
1591         fid_parms.resource_type = mark_flag;
1592         fid_parms.resource_hndl = act_idx;
1593         ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
1594
1595         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1596         if (rc)
1597                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1598         return rc;
1599 }
1600
1601 static int32_t
1602 ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms,
1603                                 struct bnxt_ulp_mapper_tbl_info *tbl)
1604 {
1605         struct ulp_flow_db_res_params fid_parms;
1606         uint32_t act_idx, mark, mark_flag;
1607         uint64_t val64;
1608         enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1609         int32_t rc = 0;
1610
1611         if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1612             mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION)
1613                 return rc; /* no need to perform mark action process */
1614
1615         /* Get the mark id details from the computed field of dev port id */
1616         mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID);
1617
1618          /* Get the main action pointer */
1619         if (!ulp_regfile_read(parms->regfile,
1620                               BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1621                               &val64)) {
1622                 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1623                 return -EINVAL;
1624         }
1625         act_idx = tfp_be_to_cpu_64(val64);
1626
1627         /* Set the mark flag to local fid and vfr flag */
1628         mark_flag  = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID;
1629
1630         rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1631                                   act_idx, mark);
1632         if (rc) {
1633                 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1634                 return rc;
1635         }
1636         fid_parms.direction = tbl->direction;
1637         fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1638         fid_parms.critical_resource = tbl->critical_resource;
1639         fid_parms.resource_type = mark_flag;
1640         fid_parms.resource_hndl = act_idx;
1641         ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
1642
1643         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1644         if (rc)
1645                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1646         return rc;
1647 }
1648
1649 /* Tcam table scan the identifier list and allocate each identifier */
1650 static int32_t
1651 ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms *parms,
1652                                      struct bnxt_ulp_mapper_tbl_info *tbl)
1653 {
1654         struct bnxt_ulp_mapper_ident_info *idents;
1655         uint32_t num_idents;
1656         uint32_t i;
1657
1658         idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1659         for (i = 0; i < num_idents; i++) {
1660                 if (ulp_mapper_ident_process(parms, tbl,
1661                                              &idents[i], NULL))
1662                         return -EINVAL;
1663         }
1664         return 0;
1665 }
1666
1667 /*
1668  * Tcam table scan the identifier list and extract the identifier from
1669  * the result blob.
1670  */
1671 static int32_t
1672 ulp_mapper_tcam_tbl_scan_ident_extract(struct bnxt_ulp_mapper_parms *parms,
1673                                        struct bnxt_ulp_mapper_tbl_info *tbl,
1674                                        struct ulp_blob *data)
1675 {
1676         struct bnxt_ulp_mapper_ident_info *idents;
1677         uint32_t num_idents = 0, i;
1678         int32_t rc = 0;
1679
1680         /*
1681          * Extract the listed identifiers from the result field,
1682          * no need to allocate them.
1683          */
1684         idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1685         for (i = 0; i < num_idents; i++) {
1686                 rc = ulp_mapper_ident_extract(parms, tbl, &idents[i], data);
1687                 if (rc) {
1688                         BNXT_TF_DBG(ERR, "Error in identifier extraction\n");
1689                         return rc;
1690                 }
1691         }
1692         return rc;
1693 }
1694
1695 /* Internal function to write the tcam entry */
1696 static int32_t
1697 ulp_mapper_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms,
1698                                 struct bnxt_ulp_mapper_tbl_info *tbl,
1699                                 struct ulp_blob *key,
1700                                 struct ulp_blob *mask,
1701                                 struct ulp_blob *data,
1702                                 uint16_t idx)
1703 {
1704         struct tf_set_tcam_entry_parms sparms = { 0 };
1705         struct tf *tfp;
1706         uint16_t tmplen;
1707         int32_t rc;
1708
1709         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
1710         if (!tfp) {
1711                 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1712                 return -EINVAL;
1713         }
1714
1715         sparms.dir              = tbl->direction;
1716         sparms.tcam_tbl_type    = tbl->resource_type;
1717         sparms.idx              = idx;
1718         sparms.key              = ulp_blob_data_get(key, &tmplen);
1719         sparms.key_sz_in_bits   = tmplen;
1720         sparms.mask             = ulp_blob_data_get(mask, &tmplen);
1721         sparms.result           = ulp_blob_data_get(data, &tmplen);
1722         sparms.result_sz_in_bits = tmplen;
1723         if (tf_set_tcam_entry(tfp, &sparms)) {
1724                 BNXT_TF_DBG(ERR, "tcam[%s][%s][%x] write failed.\n",
1725                             tf_tcam_tbl_2_str(sparms.tcam_tbl_type),
1726                             tf_dir_2_str(sparms.dir), sparms.idx);
1727                 return -EIO;
1728         }
1729
1730         /* Mark action */
1731         rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1732         if (rc) {
1733                 BNXT_TF_DBG(ERR, "failed mark action processing\n");
1734                 return rc;
1735         }
1736
1737         return rc;
1738 }
1739
1740 /*
1741  * internal function to post process key/mask blobs for dynamic pad WC tcam tbl
1742  *
1743  * parms [in] The mappers parms with data related to the flow.
1744  *
1745  * key [in] The original key to be transformed
1746  *
1747  * mask [in] The original mask to be transformed
1748  *
1749  * tkey [in/out] The transformed key
1750  *
1751  * tmask [in/out] The transformed mask
1752  *
1753  * returns zero on success, non-zero on failure
1754  */
1755 static uint32_t
1756 ulp_mapper_wc_tcam_tbl_dyn_post_process(struct bnxt_ulp_device_params *dparms,
1757                                         struct ulp_blob *key,
1758                                         struct ulp_blob *mask,
1759                                         struct ulp_blob *tkey,
1760                                         struct ulp_blob *tmask)
1761 {
1762         uint16_t tlen, blen, clen, slice_width, num_slices, max_slices, offset;
1763         uint32_t cword, i, rc;
1764         int32_t pad;
1765         uint8_t *val;
1766
1767         slice_width = dparms->wc_slice_width;
1768         clen = dparms->wc_ctl_size_bits;
1769         max_slices = dparms->wc_max_slices;
1770         blen = ulp_blob_data_len_get(key);
1771
1772         /* Get the length of the key based on number of slices and width */
1773         num_slices = 1;
1774         tlen = slice_width;
1775         while (tlen < blen &&
1776                num_slices <= max_slices) {
1777                 num_slices = num_slices << 1;
1778                 tlen = tlen << 1;
1779         }
1780
1781         if (num_slices > max_slices) {
1782                 BNXT_TF_DBG(ERR, "Key size (%d) too large for WC\n", blen);
1783                 return -EINVAL;
1784         }
1785
1786         /* The key/mask may not be on a natural slice boundary, pad it */
1787         pad = tlen - blen;
1788         if (ulp_blob_pad_push(key, pad) < 0 ||
1789             ulp_blob_pad_push(mask, pad) < 0) {
1790                 BNXT_TF_DBG(ERR, "Unable to pad key/mask\n");
1791                 return -EINVAL;
1792         }
1793
1794         /* The new length accounts for the ctrl word length and num slices */
1795         tlen = tlen + clen * num_slices;
1796         if (!ulp_blob_init(tkey, tlen, key->byte_order) ||
1797             !ulp_blob_init(tmask, tlen, mask->byte_order)) {
1798                 BNXT_TF_DBG(ERR, "Unable to post process wc tcam entry\n");
1799                 return -EINVAL;
1800         }
1801
1802         /* Build the transformed key/mask */
1803         cword = dparms->wc_mode_list[num_slices - 1];
1804         cword = tfp_cpu_to_be_32(cword);
1805         offset = 0;
1806         for (i = 0; i < num_slices; i++) {
1807                 val = ulp_blob_push_32(tkey, &cword, clen);
1808                 if (!val) {
1809                         BNXT_TF_DBG(ERR, "Key ctrl word push failed\n");
1810                         return -EINVAL;
1811                 }
1812                 val = ulp_blob_push_32(tmask, &cword, clen);
1813                 if (!val) {
1814                         BNXT_TF_DBG(ERR, "Mask ctrl word push failed\n");
1815                         return -EINVAL;
1816                 }
1817                 rc = ulp_blob_append(tkey, key, offset, slice_width);
1818                 if (rc) {
1819                         BNXT_TF_DBG(ERR, "Key blob append failed\n");
1820                         return rc;
1821                 }
1822                 rc = ulp_blob_append(tmask, mask, offset, slice_width);
1823                 if (rc) {
1824                         BNXT_TF_DBG(ERR, "Mask blob append failed\n");
1825                         return rc;
1826                 }
1827                 offset += slice_width;
1828         }
1829
1830         /* The key/mask are byte reversed on every 4 byte chunk */
1831         ulp_blob_perform_byte_reverse(tkey, 4);
1832         ulp_blob_perform_byte_reverse(tmask, 4);
1833
1834         return 0;
1835 }
1836
1837 /* internal function to post process the key/mask blobs for wildcard tcam tbl */
1838 static void ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob *blob)
1839 {
1840         ulp_blob_perform_64B_word_swap(blob);
1841         ulp_blob_perform_64B_byte_swap(blob);
1842 }
1843
1844 static int32_t
1845 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1846                             struct bnxt_ulp_mapper_tbl_info *tbl)
1847 {
1848         struct bnxt_ulp_mapper_key_info *kflds;
1849         struct ulp_blob okey, omask, data, update_data;
1850         struct ulp_blob tkey, tmask; /* transform key and mask */
1851         struct ulp_blob *key, *mask;
1852         uint32_t i, num_kflds;
1853         struct tf *tfp;
1854         int32_t rc, trc;
1855         struct bnxt_ulp_device_params *dparms = parms->device_params;
1856         struct tf_alloc_tcam_entry_parms aparms         = { 0 };
1857         struct tf_search_tcam_entry_parms searchparms   = { 0 };
1858         struct ulp_flow_db_res_params   fid_parms       = { 0 };
1859         struct tf_free_tcam_entry_parms free_parms      = { 0 };
1860         uint32_t hit = 0;
1861         uint16_t tmplen = 0;
1862         uint16_t idx;
1863
1864         /* Set the key and mask to the original key and mask. */
1865         key = &okey;
1866         mask = &omask;
1867
1868         /* Skip this if table opcode is NOP */
1869         if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_NOT_USED ||
1870             tbl->tbl_opcode >= BNXT_ULP_TCAM_TBL_OPC_LAST) {
1871                 BNXT_TF_DBG(ERR, "Invalid tcam table opcode %d\n",
1872                             tbl->tbl_opcode);
1873                 return 0;
1874         }
1875
1876         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
1877         if (!tfp) {
1878                 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1879                 return -EINVAL;
1880         }
1881
1882         kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
1883         if (!kflds || !num_kflds) {
1884                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1885                 return -EINVAL;
1886         }
1887
1888         if (!ulp_blob_init(key, tbl->blob_key_bit_size, tbl->byte_order) ||
1889             !ulp_blob_init(mask, tbl->blob_key_bit_size, tbl->byte_order) ||
1890             !ulp_blob_init(&data, tbl->result_bit_size, dparms->byte_order) ||
1891             !ulp_blob_init(&update_data, tbl->result_bit_size,
1892                            dparms->byte_order)) {
1893                 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1894                 return -EINVAL;
1895         }
1896
1897         /* create the key/mask */
1898         /*
1899          * NOTE: The WC table will require some kind of flag to handle the
1900          * mode bits within the key/mask
1901          */
1902         for (i = 0; i < num_kflds; i++) {
1903                 /* Setup the key */
1904                 rc = ulp_mapper_field_opc_process(parms, tbl->direction,
1905                                                   &kflds[i].field_info_spec,
1906                                                   key, 1, "TCAM Key");
1907                 if (rc) {
1908                         BNXT_TF_DBG(ERR, "Key field set failed %s\n",
1909                                     kflds[i].field_info_spec.description);
1910                         return rc;
1911                 }
1912
1913                 /* Setup the mask */
1914                 rc = ulp_mapper_field_opc_process(parms, tbl->direction,
1915                                                   &kflds[i].field_info_mask,
1916                                                   mask, 0, "TCAM Mask");
1917                 if (rc) {
1918                         BNXT_TF_DBG(ERR, "Mask field set failed %s\n",
1919                                     kflds[i].field_info_mask.description);
1920                         return rc;
1921                 }
1922         }
1923
1924         /* For wild card tcam perform the post process to swap the blob */
1925         if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM ||
1926             tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM_HIGH ||
1927             tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM_LOW) {
1928                 if (dparms->dynamic_pad_en) {
1929                         /* Sets up the slices for writing to the WC TCAM */
1930                         rc = ulp_mapper_wc_tcam_tbl_dyn_post_process(dparms,
1931                                                                      key, mask,
1932                                                                      &tkey,
1933                                                                      &tmask);
1934                         if (rc) {
1935                                 BNXT_TF_DBG(ERR,
1936                                             "Failed to post proc WC entry.\n");
1937                                 return rc;
1938                         }
1939                         /* Now need to use the transform Key/Mask */
1940                         key = &tkey;
1941                         mask = &tmask;
1942                 } else {
1943                         ulp_mapper_wc_tcam_tbl_post_process(key);
1944                         ulp_mapper_wc_tcam_tbl_post_process(mask);
1945                 }
1946
1947         }
1948
1949         if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
1950                 /* allocate the tcam index */
1951                 aparms.dir = tbl->direction;
1952                 aparms.tcam_tbl_type = tbl->resource_type;
1953                 aparms.key = ulp_blob_data_get(key, &tmplen);
1954                 aparms.key_sz_in_bits = tmplen;
1955                 aparms.mask = ulp_blob_data_get(mask, &tmplen);
1956
1957                 /* calculate the entry priority */
1958                 rc = ulp_mapper_priority_opc_process(parms, tbl,
1959                                                      &aparms.priority);
1960                 if (rc) {
1961                         BNXT_TF_DBG(ERR, "entry priority process failed\n");
1962                         return rc;
1963                 }
1964
1965                 rc = tf_alloc_tcam_entry(tfp, &aparms);
1966                 if (rc) {
1967                         BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
1968                         return rc;
1969                 }
1970                 idx = aparms.idx;
1971                 hit = aparms.hit;
1972         } else {
1973                 /*
1974                  * Searching before allocation to see if we already have an
1975                  * entry.  This allows re-use of a constrained resource.
1976                  */
1977                 searchparms.dir = tbl->direction;
1978                 searchparms.tcam_tbl_type = tbl->resource_type;
1979                 searchparms.key = ulp_blob_data_get(key, &tmplen);
1980                 searchparms.key_sz_in_bits = tbl->key_bit_size;
1981                 searchparms.mask = ulp_blob_data_get(mask, &tmplen);
1982                 searchparms.alloc = 1;
1983                 searchparms.result = ulp_blob_data_get(&data, &tmplen);
1984                 searchparms.result_sz_in_bits = tbl->result_bit_size;
1985
1986                 /* calculate the entry priority */
1987                 rc = ulp_mapper_priority_opc_process(parms, tbl,
1988                                                      &searchparms.priority);
1989                 if (rc) {
1990                         BNXT_TF_DBG(ERR, "entry priority process failed\n");
1991                         return rc;
1992                 }
1993
1994                 rc = tf_search_tcam_entry(tfp, &searchparms);
1995                 if (rc) {
1996                         BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc);
1997                         return rc;
1998                 }
1999
2000                 /* Successful search, check the result */
2001                 if (searchparms.search_status == REJECT) {
2002                         BNXT_TF_DBG(ERR, "tcam alloc rejected\n");
2003                         return -ENOMEM;
2004                 }
2005                 idx = searchparms.idx;
2006                 hit = searchparms.hit;
2007         }
2008
2009         /* Write the tcam index into the regfile*/
2010         if (ulp_regfile_write(parms->regfile, tbl->tbl_operand,
2011                               (uint64_t)tfp_cpu_to_be_64(idx))) {
2012                 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
2013                             tbl->tbl_operand);
2014                 rc = -EINVAL;
2015                 /* Need to free the tcam idx, so goto error */
2016                 goto error;
2017         }
2018
2019         /* if it is miss then it is same as no search before alloc */
2020         if (!hit || tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
2021                 /*Scan identifier list, allocate identifier and update regfile*/
2022                 rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl);
2023                 /* Create the result blob */
2024                 if (!rc)
2025                         rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
2026                                                          "TCAM Result");
2027                 /* write the tcam entry */
2028                 if (!rc)
2029                         rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, key,
2030                                                              mask, &data, idx);
2031         } else {
2032                 /*Scan identifier list, extract identifier and update regfile*/
2033                 rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data);
2034         }
2035         if (rc)
2036                 goto error;
2037
2038         /* Add the tcam index to the flow database */
2039         fid_parms.direction = tbl->direction;
2040         fid_parms.resource_func = tbl->resource_func;
2041         fid_parms.resource_type = tbl->resource_type;
2042         fid_parms.critical_resource = tbl->critical_resource;
2043         fid_parms.resource_hndl = idx;
2044         ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
2045
2046         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2047         if (rc) {
2048                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
2049                             rc);
2050                 /* Need to free the identifier, so goto error */
2051                 goto error;
2052         }
2053
2054         return 0;
2055 error:
2056         free_parms.dir                  = tbl->direction;
2057         free_parms.tcam_tbl_type        = tbl->resource_type;
2058         free_parms.idx                  = idx;
2059         trc = tf_free_tcam_entry(tfp, &free_parms);
2060         if (trc)
2061                 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
2062                             tbl->resource_type, tbl->direction, idx);
2063         return rc;
2064 }
2065
2066 static int32_t
2067 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2068                           struct bnxt_ulp_mapper_tbl_info *tbl)
2069 {
2070         struct bnxt_ulp_mapper_key_info *kflds;
2071         struct ulp_blob key, data;
2072         uint32_t i, num_kflds;
2073         uint16_t tmplen;
2074         struct tf *tfp;
2075         struct ulp_flow_db_res_params   fid_parms = { 0 };
2076         struct tf_insert_em_entry_parms iparms = { 0 };
2077         struct tf_delete_em_entry_parms free_parms = { 0 };
2078         enum bnxt_ulp_flow_mem_type mtype;
2079         struct bnxt_ulp_device_params *dparms = parms->device_params;
2080         int32_t trc;
2081         int32_t rc = 0;
2082         int32_t pad = 0;
2083
2084         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
2085         rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype);
2086         if (rc) {
2087                 BNXT_TF_DBG(ERR, "Failed to get the mem type for EM\n");
2088                 return -EINVAL;
2089         }
2090
2091         kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2092         if (!kflds || !num_kflds) {
2093                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2094                 return -EINVAL;
2095         }
2096
2097         /* Initialize the key/result blobs */
2098         if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
2099                            tbl->byte_order) ||
2100             !ulp_blob_init(&data, tbl->result_bit_size,
2101                            tbl->byte_order)) {
2102                 BNXT_TF_DBG(ERR, "blob inits failed.\n");
2103                 return -EINVAL;
2104         }
2105
2106         /* create the key */
2107         for (i = 0; i < num_kflds; i++) {
2108                 /* Setup the key */
2109                 rc = ulp_mapper_field_opc_process(parms, tbl->direction,
2110                                                   &kflds[i].field_info_spec,
2111                                                   &key, 1, "EM Key");
2112                 if (rc) {
2113                         BNXT_TF_DBG(ERR, "Key field set failed.\n");
2114                         return rc;
2115                 }
2116         }
2117
2118         /* if dynamic padding is enabled then add padding to result data */
2119         if (dparms->dynamic_pad_en) {
2120                 /* add padding to make sure key is at byte boundary */
2121                 ulp_blob_pad_align(&key, ULP_BUFFER_ALIGN_8_BITS);
2122
2123                 /* add the pad */
2124                 pad = dparms->em_blk_align_bits - dparms->em_blk_size_bits;
2125                 if (pad < 0) {
2126                         BNXT_TF_DBG(ERR, "Invalid em blk size and align\n");
2127                         return -EINVAL;
2128                 }
2129                 ulp_blob_pad_push(&data, (uint32_t)pad);
2130         }
2131
2132         /* Create the result data blob */
2133         rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "EM Result");
2134         if (rc) {
2135                 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2136                 return rc;
2137         }
2138         if (dparms->dynamic_pad_en) {
2139                 uint32_t abits = dparms->em_blk_align_bits;
2140
2141                 /* when dynamic padding is enabled merge result + key */
2142                 rc = ulp_blob_block_merge(&data, &key, abits, pad);
2143                 if (rc) {
2144                         BNXT_TF_DBG(ERR, "Failed to merge the result blob\n");
2145                         return rc;
2146                 }
2147
2148                 /* add padding to make sure merged result is at slice boundary*/
2149                 ulp_blob_pad_align(&data, abits);
2150
2151                 ulp_blob_perform_byte_reverse(&data, ULP_BITS_2_BYTE(abits));
2152         }
2153
2154         /* do the transpose for the internal EM keys */
2155         if (tbl->resource_type == TF_MEM_INTERNAL) {
2156                 if (dparms->em_key_align_bytes) {
2157                         int32_t b = ULP_BYTE_2_BITS(dparms->em_key_align_bytes);
2158
2159                         tmplen = ulp_blob_data_len_get(&key);
2160                         ulp_blob_pad_push(&key, b - tmplen);
2161                 }
2162                 tmplen = ulp_blob_data_len_get(&key);
2163                 ulp_blob_perform_byte_reverse(&key, ULP_BITS_2_BYTE(tmplen));
2164         }
2165
2166         rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
2167                                              &iparms.tbl_scope_id);
2168         if (rc) {
2169                 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
2170                 return rc;
2171         }
2172
2173         /*
2174          * NOTE: the actual blob size will differ from the size in the tbl
2175          * entry due to the padding.
2176          */
2177         iparms.dup_check                = 0;
2178         iparms.dir                      = tbl->direction;
2179         iparms.mem                      = tbl->resource_type;
2180         iparms.key                      = ulp_blob_data_get(&key, &tmplen);
2181         iparms.key_sz_in_bits           = tbl->key_bit_size;
2182         iparms.em_record                = ulp_blob_data_get(&data, &tmplen);
2183         if (tbl->result_bit_size)
2184                 iparms.em_record_sz_in_bits     = tbl->result_bit_size;
2185         else
2186                 iparms.em_record_sz_in_bits     = tmplen;
2187
2188         rc = tf_insert_em_entry(tfp, &iparms);
2189         if (rc) {
2190                 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
2191                 return rc;
2192         }
2193
2194         /* Mark action process */
2195         if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT &&
2196             tbl->resource_type == TF_MEM_EXTERNAL)
2197                 rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id);
2198         else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT &&
2199                  tbl->resource_type == TF_MEM_INTERNAL)
2200                 rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
2201         if (rc) {
2202                 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
2203                 goto error;
2204         }
2205
2206         /* Link the EM resource to the flow in the flow db */
2207         memset(&fid_parms, 0, sizeof(fid_parms));
2208         fid_parms.direction             = tbl->direction;
2209         fid_parms.resource_func         = tbl->resource_func;
2210         fid_parms.resource_type         = tbl->resource_type;
2211         fid_parms.critical_resource     = tbl->critical_resource;
2212         fid_parms.resource_hndl         = iparms.flow_handle;
2213
2214         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2215         if (rc) {
2216                 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
2217                             rc);
2218                 /* Need to free the identifier, so goto error */
2219                 goto error;
2220         }
2221
2222         return 0;
2223 error:
2224         free_parms.dir          = iparms.dir;
2225         free_parms.mem          = iparms.mem;
2226         free_parms.tbl_scope_id = iparms.tbl_scope_id;
2227         free_parms.flow_handle  = iparms.flow_handle;
2228
2229         trc = tf_delete_em_entry(tfp, &free_parms);
2230         if (trc)
2231                 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
2232
2233         return rc;
2234 }
2235
2236 static int32_t
2237 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2238                              struct bnxt_ulp_mapper_tbl_info *tbl)
2239 {
2240         struct ulp_flow_db_res_params fid_parms;
2241         struct ulp_blob data;
2242         uint64_t regval = 0;
2243         uint16_t tmplen;
2244         uint32_t index;
2245         int32_t rc = 0, trc = 0;
2246         struct tf_alloc_tbl_entry_parms aparms = { 0 };
2247         struct tf_set_tbl_entry_parms sparms = { 0 };
2248         struct tf_get_tbl_entry_parms gparms = { 0 };
2249         struct tf_free_tbl_entry_parms free_parms = { 0 };
2250         uint32_t tbl_scope_id;
2251         struct tf *tfp;
2252         struct bnxt_ulp_glb_resource_info glb_res = { 0 };
2253         uint16_t bit_size;
2254         bool alloc = false;
2255         bool write = false;
2256         bool global = false;
2257         uint64_t act_rec_size;
2258         bool shared = false;
2259
2260         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
2261         /* use the max size if encap is enabled */
2262         if (tbl->encap_num_fields)
2263                 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
2264         else
2265                 bit_size = tbl->result_bit_size;
2266
2267         /* Initialize the blob data */
2268         if (!ulp_blob_init(&data, bit_size,
2269                            parms->device_params->byte_order)) {
2270                 BNXT_TF_DBG(ERR, "Failed to initialize index table blob\n");
2271                 return -EINVAL;
2272         }
2273
2274         /* Get the scope id first */
2275         rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
2276         if (rc) {
2277                 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
2278                 return rc;
2279         }
2280
2281         switch (tbl->tbl_opcode) {
2282         case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE:
2283                 alloc = true;
2284                 break;
2285         case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE:
2286                 /*
2287                  * Build the entry, alloc an index, write the table, and store
2288                  * the data in the regfile.
2289                  */
2290                 alloc = true;
2291                 write = true;
2292                 break;
2293         case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE:
2294                 /*
2295                  * get the index to write to from the regfile and then write
2296                  * the table entry.
2297                  */
2298                 if (!ulp_regfile_read(parms->regfile,
2299                                       tbl->tbl_operand,
2300                                       &regval)) {
2301                         BNXT_TF_DBG(ERR,
2302                                     "Failed to get tbl idx from regfile[%d].\n",
2303                                     tbl->tbl_operand);
2304                         return -EINVAL;
2305                 }
2306                 index = tfp_be_to_cpu_64(regval);
2307                 /* For external, we need to reverse shift */
2308                 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2309                         index = TF_ACT_REC_PTR_2_OFFSET(index);
2310
2311                 write = true;
2312                 break;
2313         case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_GLB_REGFILE:
2314                 /*
2315                  * Build the entry, alloc an index, write the table, and store
2316                  * the data in the global regfile.
2317                  */
2318                 alloc = true;
2319                 global = true;
2320                 write = true;
2321                 glb_res.direction = tbl->direction;
2322                 glb_res.resource_func = tbl->resource_func;
2323                 glb_res.resource_type = tbl->resource_type;
2324                 glb_res.glb_regfile_index = tbl->tbl_operand;
2325                 break;
2326         case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE:
2327                 if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) {
2328                         BNXT_TF_DBG(ERR, "Template error, wrong fdb opcode\n");
2329                         return -EINVAL;
2330                 }
2331                 /*
2332                  * get the index to write to from the global regfile and then
2333                  * write the table.
2334                  */
2335                 if (ulp_mapper_glb_resource_read(parms->mapper_data,
2336                                                  tbl->direction,
2337                                                  tbl->tbl_operand,
2338                                                  &regval, &shared)) {
2339                         BNXT_TF_DBG(ERR,
2340                                     "Failed to get tbl idx from Glb RF[%d].\n",
2341                                     tbl->tbl_operand);
2342                         return -EINVAL;
2343                 }
2344                 index = tfp_be_to_cpu_64(regval);
2345                 /* For external, we need to reverse shift */
2346                 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2347                         index = TF_ACT_REC_PTR_2_OFFSET(index);
2348                 write = true;
2349                 break;
2350         case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE:
2351                 /*
2352                  * The read is different from the rest and can be handled here
2353                  * instead of trying to use common code.  Simply read the table
2354                  * with the index from the regfile, scan and store the
2355                  * identifiers, and return.
2356                  */
2357                 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2358                         /* Not currently supporting with EXT */
2359                         BNXT_TF_DBG(ERR,
2360                                     "Ext Table Read Opcode not supported.\n");
2361                         return -EINVAL;
2362                 }
2363                 if (!ulp_regfile_read(parms->regfile,
2364                                       tbl->tbl_operand, &regval)) {
2365                         BNXT_TF_DBG(ERR,
2366                                     "Failed to get tbl idx from regfile[%d]\n",
2367                                     tbl->tbl_operand);
2368                         return -EINVAL;
2369                 }
2370                 index = tfp_be_to_cpu_64(regval);
2371                 gparms.dir = tbl->direction;
2372                 gparms.type = tbl->resource_type;
2373                 gparms.data = ulp_blob_data_get(&data, &tmplen);
2374                 gparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tbl->result_bit_size);
2375                 gparms.idx = index;
2376                 rc = tf_get_tbl_entry(tfp, &gparms);
2377                 if (rc) {
2378                         BNXT_TF_DBG(ERR, "Failed to read the tbl entry %d:%d\n",
2379                                     tbl->resource_type, index);
2380                         return rc;
2381                 }
2382                 /*
2383                  * Scan the fields in the entry and push them into the regfile.
2384                  */
2385                 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2386                                                    gparms.data,
2387                                                    gparms.data_sz_in_bytes,
2388                                                    data.byte_order);
2389                 if (rc) {
2390                         BNXT_TF_DBG(ERR,
2391                                     "Failed to get flds on tbl read rc=%d\n",
2392                                     rc);
2393                         return rc;
2394                 }
2395                 return 0;
2396         default:
2397                 BNXT_TF_DBG(ERR, "Invalid index table opcode %d\n",
2398                             tbl->tbl_opcode);
2399                 return -EINVAL;
2400         }
2401
2402         if (write) {
2403                 /* Get the result fields list */
2404                 rc = ulp_mapper_tbl_result_build(parms,
2405                                                  tbl,
2406                                                  &data,
2407                                                  "Indexed Result");
2408                 if (rc) {
2409                         BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2410                         return rc;
2411                 }
2412         }
2413
2414         if (alloc) {
2415                 aparms.dir              = tbl->direction;
2416                 aparms.type             = tbl->resource_type;
2417                 aparms.tbl_scope_id     = tbl_scope_id;
2418
2419                 /* All failures after the alloc succeeds require a free */
2420                 rc = tf_alloc_tbl_entry(tfp, &aparms);
2421                 if (rc) {
2422                         BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2423                                     tf_tbl_type_2_str(tbl->resource_type),
2424                                     tf_dir_2_str(tbl->direction), rc);
2425                         return rc;
2426                 }
2427                 index = aparms.idx;
2428
2429                 /*
2430                  * Store the index in the regfile since we either allocated it
2431                  * or it was a hit.
2432                  *
2433                  * Calculate the idx for the result record, for external EM the
2434                  * offset needs to be shifted accordingly.
2435                  * If external non-inline table types are used then need to
2436                  * revisit this logic.
2437                  */
2438                 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2439                         regval = TF_ACT_REC_OFFSET_2_PTR(index);
2440                 else
2441                         regval = index;
2442                 regval = tfp_cpu_to_be_64(regval);
2443
2444                 if (global) {
2445                         /*
2446                          * Shared resources are never allocated through this
2447                          * method, so the shared flag is always false.
2448                          */
2449                         rc = ulp_mapper_glb_resource_write(parms->mapper_data,
2450                                                            &glb_res, regval,
2451                                                            false);
2452                 } else {
2453                         rc = ulp_regfile_write(parms->regfile,
2454                                                tbl->tbl_operand, regval);
2455                 }
2456                 if (rc) {
2457                         BNXT_TF_DBG(ERR,
2458                                     "Failed to write %s regfile[%d] rc=%d\n",
2459                                     (global) ? "global" : "reg",
2460                                     tbl->tbl_operand, rc);
2461                         goto error;
2462                 }
2463         }
2464
2465         if (write) {
2466                 sparms.dir = tbl->direction;
2467                 sparms.type = tbl->resource_type;
2468                 sparms.data = ulp_blob_data_get(&data, &tmplen);
2469                 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2470                 sparms.idx = index;
2471                 sparms.tbl_scope_id = tbl_scope_id;
2472                 if (shared)
2473                         tfp = bnxt_ulp_cntxt_shared_tfp_get(parms->ulp_ctx);
2474                 rc = tf_set_tbl_entry(tfp, &sparms);
2475                 if (rc) {
2476                         BNXT_TF_DBG(ERR,
2477                                     "Index table[%s][%s][%x] write fail rc=%d\n",
2478                                     tf_tbl_type_2_str(sparms.type),
2479                                     tf_dir_2_str(sparms.dir),
2480                                     sparms.idx, rc);
2481                         goto error;
2482                 }
2483
2484                 /* Calculate action record size */
2485                 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2486                         act_rec_size = (ULP_BITS_2_BYTE_NR(tmplen) + 15) / 16;
2487                         act_rec_size--;
2488                         if (ulp_regfile_write(parms->regfile,
2489                                               BNXT_ULP_RF_IDX_ACTION_REC_SIZE,
2490                                               tfp_cpu_to_be_64(act_rec_size)))
2491                                 BNXT_TF_DBG(ERR,
2492                                             "Failed write the act rec size\n");
2493                 }
2494         }
2495
2496         /* Link the resource to the flow in the flow db */
2497         memset(&fid_parms, 0, sizeof(fid_parms));
2498         fid_parms.direction     = tbl->direction;
2499         fid_parms.resource_func = tbl->resource_func;
2500         fid_parms.resource_type = tbl->resource_type;
2501         fid_parms.resource_sub_type = tbl->resource_sub_type;
2502         fid_parms.resource_hndl = index;
2503         fid_parms.critical_resource = tbl->critical_resource;
2504         ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
2505
2506         rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2507         if (rc) {
2508                 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
2509                             rc);
2510                 goto error;
2511         }
2512
2513         /* Perform the VF rep action */
2514         rc = ulp_mapper_mark_vfr_idx_process(parms, tbl);
2515         if (rc) {
2516                 BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc);
2517                 goto error;
2518         }
2519         return rc;
2520 error:
2521         /* Shared resources are not freed */
2522         if (shared)
2523                 return rc;
2524         /*
2525          * Free the allocated resource since we failed to either
2526          * write to the entry or link the flow
2527          */
2528         free_parms.dir  = tbl->direction;
2529         free_parms.type = tbl->resource_type;
2530         free_parms.idx  = index;
2531         free_parms.tbl_scope_id = tbl_scope_id;
2532
2533         trc = tf_free_tbl_entry(tfp, &free_parms);
2534         if (trc)
2535                 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
2536
2537         return rc;
2538 }
2539
2540 static int32_t
2541 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2542                           struct bnxt_ulp_mapper_tbl_info *tbl)
2543 {
2544         struct ulp_blob data, res_blob;
2545         uint64_t idx;
2546         uint16_t tmplen;
2547         int32_t rc = 0;
2548         struct tf_set_if_tbl_entry_parms iftbl_params = { 0 };
2549         struct tf_get_if_tbl_entry_parms get_parms = { 0 };
2550         struct tf *tfp;
2551         enum bnxt_ulp_if_tbl_opc if_opc = tbl->tbl_opcode;
2552         uint32_t res_size;
2553
2554         tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx, tbl->shared_session);
2555         /* Initialize the blob data */
2556         if (!ulp_blob_init(&data, tbl->result_bit_size,
2557                            parms->device_params->byte_order)) {
2558                 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2559                 return -EINVAL;
2560         }
2561
2562         /* create the result blob */
2563         rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "IFtable Result");
2564         if (rc) {
2565                 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2566                 return rc;
2567         }
2568
2569         /* Get the index details */
2570         switch (if_opc) {
2571         case BNXT_ULP_IF_TBL_OPC_WR_COMP_FIELD:
2572                 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2573                 break;
2574         case BNXT_ULP_IF_TBL_OPC_WR_REGFILE:
2575                 if (!ulp_regfile_read(parms->regfile, tbl->tbl_operand, &idx)) {
2576                         BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2577                                     tbl->tbl_operand);
2578                         return -EINVAL;
2579                 }
2580                 idx = tfp_be_to_cpu_64(idx);
2581                 break;
2582         case BNXT_ULP_IF_TBL_OPC_WR_CONST:
2583                 idx = tbl->tbl_operand;
2584                 break;
2585         case BNXT_ULP_IF_TBL_OPC_RD_COMP_FIELD:
2586                 /* Initialize the result blob */
2587                 if (!ulp_blob_init(&res_blob, tbl->result_bit_size,
2588                                    parms->device_params->byte_order)) {
2589                         BNXT_TF_DBG(ERR, "Failed initial result blob\n");
2590                         return -EINVAL;
2591                 }
2592
2593                 /* read the interface table */
2594                 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2595                 res_size = ULP_BITS_2_BYTE(tbl->result_bit_size);
2596                 get_parms.dir = tbl->direction;
2597                 get_parms.type = tbl->resource_type;
2598                 get_parms.idx = idx;
2599                 get_parms.data = ulp_blob_data_get(&res_blob, &tmplen);
2600                 get_parms.data_sz_in_bytes = res_size;
2601
2602                 rc = tf_get_if_tbl_entry(tfp, &get_parms);
2603                 if (rc) {
2604                         BNXT_TF_DBG(ERR, "Get table[%d][%s][%x] failed rc=%d\n",
2605                                     get_parms.type,
2606                                     tf_dir_2_str(get_parms.dir),
2607                                     get_parms.idx, rc);
2608                         return rc;
2609                 }
2610                 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2611                                                    res_blob.data,
2612                                                    res_size,
2613                                                    res_blob.byte_order);
2614                 if (rc)
2615                         BNXT_TF_DBG(ERR, "Scan and extract failed rc=%d\n", rc);
2616                 return rc;
2617         case BNXT_ULP_IF_TBL_OPC_NOT_USED:
2618                 return rc; /* skip it */
2619         default:
2620                 BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n");
2621                 return -EINVAL;
2622         }
2623
2624         /* Perform the tf table set by filling the set params */
2625         iftbl_params.dir = tbl->direction;
2626         iftbl_params.type = tbl->resource_type;
2627         iftbl_params.data = ulp_blob_data_get(&data, &tmplen);
2628         iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2629         iftbl_params.idx = idx;
2630
2631         rc = tf_set_if_tbl_entry(tfp, &iftbl_params);
2632         if (rc) {
2633                 BNXT_TF_DBG(ERR, "Set table[%d][%s][%x] failed rc=%d\n",
2634                             iftbl_params.type,/* TBD: add tf_if_tbl_2_str */
2635                             tf_dir_2_str(iftbl_params.dir),
2636                             iftbl_params.idx, rc);
2637                 return rc;
2638         }
2639
2640         /*
2641          * TBD: Need to look at the need to store idx in flow db for restore
2642          * the table to its original state on deletion of this entry.
2643          */
2644         return rc;
2645 }
2646
2647 static int32_t
2648 ulp_mapper_gen_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2649                            struct bnxt_ulp_mapper_tbl_info *tbl)
2650 {
2651         struct ulp_mapper_gen_tbl_list *gen_tbl_list;
2652         struct bnxt_ulp_mapper_key_info *kflds;
2653         struct ulp_flow_db_res_params fid_parms;
2654         struct ulp_mapper_gen_tbl_entry gen_tbl_ent, *g;
2655         struct ulp_gen_hash_entry_params hash_entry;
2656         uint16_t tmplen = 0;
2657         struct ulp_blob key, data;
2658         uint8_t *cache_key;
2659         int32_t tbl_idx;
2660         uint32_t i, num_kflds = 0, key_index = 0;
2661         uint32_t gen_tbl_miss = 1, fdb_write = 0;
2662         uint8_t *byte_data;
2663         int32_t rc = 0;
2664
2665         /* Get the key fields list and build the key. */
2666         kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2667         if (!kflds || !num_kflds) {
2668                 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2669                 return -EINVAL;
2670         }
2671
2672         if (!ulp_blob_init(&key, tbl->key_bit_size,
2673                            parms->device_params->byte_order)) {
2674                 BNXT_TF_DBG(ERR, "Failed to alloc blob\n");
2675                 return -EINVAL;
2676         }
2677         for (i = 0; i < num_kflds; i++) {
2678                 /* Setup the key */
2679                 rc = ulp_mapper_field_opc_process(parms, tbl->direction,
2680                                                   &kflds[i].field_info_spec,
2681                                                   &key, 1, "Gen Tbl Key");
2682                 if (rc) {
2683                         BNXT_TF_DBG(ERR,
2684                                     "Failed to create key for Gen tbl rc=%d\n",
2685                                     rc);
2686                         return -EINVAL;
2687                 }
2688         }
2689
2690         /* Calculate the table index for the generic table*/
2691         tbl_idx = ulp_mapper_gen_tbl_idx_calculate(tbl->resource_sub_type,
2692                                                    tbl->direction);
2693         if (tbl_idx < 0) {
2694                 BNXT_TF_DBG(ERR, "Invalid table index %x:%x\n",
2695                             tbl->resource_sub_type, tbl->direction);
2696                 return -EINVAL;
2697         }
2698
2699         /* The_key is a byte array convert it to a search index */
2700         cache_key = ulp_blob_data_get(&key, &tmplen);
2701         /* get the generic table  */
2702         gen_tbl_list = &parms->mapper_data->gen_tbl_list[tbl_idx];
2703
2704         /* Check if generic hash table */
2705         if (gen_tbl_list->hash_tbl) {
2706                 if (tbl->gen_tbl_lkup_type !=
2707                     BNXT_ULP_GENERIC_TBL_LKUP_TYPE_HASH) {
2708                         BNXT_TF_DBG(ERR, "%s: Invalid template lkup type\n",
2709                                     gen_tbl_list->gen_tbl_name);
2710                         return -EINVAL;
2711                 }
2712                 hash_entry.key_data = cache_key;
2713                 hash_entry.key_length = ULP_BITS_2_BYTE(tmplen);
2714                 rc = ulp_gen_hash_tbl_list_key_search(gen_tbl_list->hash_tbl,
2715                                                       &hash_entry);
2716                 if (rc) {
2717                         BNXT_TF_DBG(ERR, "%s: hash tbl search failed\n",
2718                                     gen_tbl_list->gen_tbl_name);
2719                         return rc;
2720                 }
2721                 if (hash_entry.search_flag == ULP_GEN_HASH_SEARCH_FOUND) {
2722                         key_index = hash_entry.key_idx;
2723                         /* Get the generic table entry */
2724                         if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list,
2725                                                          key_index,
2726                                                          &gen_tbl_ent))
2727                                 return -EINVAL;
2728                         /* store the hash index in the fdb */
2729                         key_index = hash_entry.hash_index;
2730                 }
2731         } else {
2732                 /* convert key to index directly */
2733                 if (ULP_BITS_2_BYTE(tmplen) > (int32_t)sizeof(key_index)) {
2734                         BNXT_TF_DBG(ERR, "%s: keysize is bigger then 4 bytes\n",
2735                                     gen_tbl_list->gen_tbl_name);
2736                         return -EINVAL;
2737                 }
2738                 memcpy(&key_index, cache_key, ULP_BITS_2_BYTE(tmplen));
2739                 /* Get the generic table entry */
2740                 if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list, key_index,
2741                                                  &gen_tbl_ent))
2742                         return -EINVAL;
2743         }
2744         switch (tbl->tbl_opcode) {
2745         case BNXT_ULP_GENERIC_TBL_OPC_READ:
2746                 if (gen_tbl_list->hash_tbl) {
2747                         if (hash_entry.search_flag != ULP_GEN_HASH_SEARCH_FOUND)
2748                                 break; /* nothing to be done , no entry */
2749                 }
2750
2751                 /* check the reference count */
2752                 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2753                         g = &gen_tbl_ent;
2754                         /* Scan ident list and create the result blob*/
2755                         rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2756                                                            g->byte_data,
2757                                                            g->byte_data_size,
2758                                                            g->byte_order);
2759                         if (rc) {
2760                                 BNXT_TF_DBG(ERR,
2761                                             "Failed to scan ident list\n");
2762                                 return -EINVAL;
2763                         }
2764                         if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) {
2765                                 /* increment the reference count */
2766                                 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2767                         }
2768
2769                         /* it is a hit */
2770                         gen_tbl_miss = 0;
2771                         fdb_write = 1;
2772                 }
2773                 break;
2774         case BNXT_ULP_GENERIC_TBL_OPC_WRITE:
2775                 if (gen_tbl_list->hash_tbl) {
2776                         rc = ulp_mapper_gen_tbl_hash_entry_add(gen_tbl_list,
2777                                                                &hash_entry,
2778                                                                &gen_tbl_ent);
2779                         if (rc)
2780                                 return rc;
2781                         /* store the hash index in the fdb */
2782                         key_index = hash_entry.hash_index;
2783                 }
2784                 /* check the reference count */
2785                 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2786                         /* a hit then error */
2787                         BNXT_TF_DBG(ERR, "generic entry already present\n");
2788                         return -EINVAL; /* success */
2789                 }
2790
2791                 /* Initialize the blob data */
2792                 if (!ulp_blob_init(&data, tbl->result_bit_size,
2793                                    gen_tbl_ent.byte_order)) {
2794                         BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2795                         return -EINVAL;
2796                 }
2797
2798                 /* Get the result fields list */
2799                 rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
2800                                                  "Gen tbl Result");
2801                 if (rc) {
2802                         BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2803                         return rc;
2804                 }
2805                 byte_data = ulp_blob_data_get(&data, &tmplen);
2806                 rc = ulp_mapper_gen_tbl_entry_data_set(&gen_tbl_ent,
2807                                                        tmplen, byte_data,
2808                                                        ULP_BITS_2_BYTE(tmplen));
2809                 if (rc) {
2810                         BNXT_TF_DBG(ERR, "Failed to write generic table\n");
2811                         return -EINVAL;
2812                 }
2813
2814                 /* increment the reference count */
2815                 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2816                 fdb_write = 1;
2817                 parms->shared_hndl = (uint64_t)tbl_idx << 32 | key_index;
2818                 break;
2819         default:
2820                 BNXT_TF_DBG(ERR, "Invalid table opcode %x\n", tbl->tbl_opcode);
2821                 return -EINVAL;
2822         }
2823
2824         /* Set the generic entry hit */
2825         rc = ulp_regfile_write(parms->regfile,
2826                                BNXT_ULP_RF_IDX_GENERIC_TBL_MISS,
2827                                tfp_cpu_to_be_64(gen_tbl_miss));
2828         if (rc) {
2829                 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
2830                             BNXT_ULP_RF_IDX_GENERIC_TBL_MISS);
2831                 return -EIO;
2832         }
2833
2834         /* add the entry to the flow database */
2835         if (fdb_write) {
2836                 memset(&fid_parms, 0, sizeof(fid_parms));
2837                 fid_parms.direction = tbl->direction;
2838                 fid_parms.resource_func = tbl->resource_func;
2839                 fid_parms.resource_sub_type = tbl->resource_sub_type;
2840                 fid_parms.resource_hndl = key_index;
2841                 fid_parms.critical_resource = tbl->critical_resource;
2842                 ulp_flow_db_shared_session_set(&fid_parms, tbl->shared_session);
2843
2844                 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2845                 if (rc)
2846                         BNXT_TF_DBG(ERR, "Fail to add gen ent flowdb %d\n", rc);
2847         }
2848         return rc;
2849 }
2850
2851 static int32_t
2852 ulp_mapper_ctrl_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2853                             struct bnxt_ulp_mapper_tbl_info *tbl)
2854 {
2855         int32_t rc = 0;
2856
2857         /* process the fdb opcode for alloc push */
2858         if (tbl->fdb_opcode == BNXT_ULP_FDB_OPC_ALLOC_RID_REGFILE) {
2859                 rc = ulp_mapper_fdb_opc_alloc_rid(parms, tbl);
2860                 if (rc) {
2861                         BNXT_TF_DBG(ERR, "Failed to do fdb alloc\n");
2862                         return rc;
2863                 }
2864         }
2865         return rc;
2866 }
2867
2868 static int32_t
2869 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx,
2870                                   struct bnxt_ulp_mapper_data *mapper_data)
2871 {
2872         struct bnxt_ulp_glb_resource_info *glb_res;
2873         uint32_t num_glb_res_ids, idx, dev_id;
2874         uint8_t app_id;
2875         int32_t rc = 0;
2876
2877         glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids);
2878         if (!glb_res || !num_glb_res_ids) {
2879                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
2880                 return -EINVAL;
2881         }
2882
2883         rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id);
2884         if (rc) {
2885                 BNXT_TF_DBG(ERR, "Failed to get device id for glb init (%d)\n",
2886                             rc);
2887                 return rc;
2888         }
2889
2890         rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id);
2891         if (rc) {
2892                 BNXT_TF_DBG(ERR, "Failed to get app id for glb init (%d)\n",
2893                             rc);
2894                 return rc;
2895         }
2896
2897         /* Iterate the global resources and process each one */
2898         for (idx = 0; idx < num_glb_res_ids; idx++) {
2899                 if (dev_id != glb_res[idx].device_id ||
2900                     glb_res[idx].app_id != app_id)
2901                         continue;
2902                 switch (glb_res[idx].resource_func) {
2903                 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
2904                         rc = ulp_mapper_resource_ident_allocate(ulp_ctx,
2905                                                                 mapper_data,
2906                                                                 &glb_res[idx]);
2907                         break;
2908                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2909                         rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx,
2910                                                                  mapper_data,
2911                                                                  &glb_res[idx]);
2912                         break;
2913                 default:
2914                         BNXT_TF_DBG(ERR, "Global resource %x not supported\n",
2915                                     glb_res[idx].resource_func);
2916                         rc = -EINVAL;
2917                         break;
2918                 }
2919                 if (rc)
2920                         return rc;
2921         }
2922         return rc;
2923 }
2924
2925 /*
2926  * Iterate over the shared resources assigned during tf_open_session and store
2927  * them in the global regfile with the shared flag.
2928  */
2929 static int32_t
2930 ulp_mapper_app_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx,
2931                                       struct bnxt_ulp_mapper_data *mapper_data)
2932 {
2933         struct tf_get_shared_tbl_increment_parms iparms;
2934         struct bnxt_ulp_glb_resource_info *glb_res;
2935         struct tf_get_session_info_parms sparms;
2936         uint32_t num_entries, i, dev_id, res;
2937         struct tf_resource_info *res_info;
2938         uint32_t addend;
2939         uint64_t regval;
2940         enum tf_dir dir;
2941         int32_t rc = 0;
2942         struct tf *tfp;
2943         uint8_t app_id;
2944
2945         memset(&sparms, 0, sizeof(sparms));
2946         glb_res = bnxt_ulp_app_glb_resource_info_list_get(&num_entries);
2947         if (!glb_res || !num_entries) {
2948                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
2949                 return -EINVAL;
2950         }
2951         tfp = bnxt_ulp_cntxt_shared_tfp_get(ulp_ctx);
2952         if (!tfp) {
2953                 BNXT_TF_DBG(ERR, "Failed to get tfp for app global init");
2954                 return -EINVAL;
2955         }
2956         /*
2957          * Retrieve the resources that were assigned during the shared session
2958          * creation.
2959          */
2960         rc = tf_get_session_info(tfp, &sparms);
2961         if (rc) {
2962                 BNXT_TF_DBG(ERR, "Failed to get session info (%d)\n", rc);
2963                 return rc;
2964         }
2965
2966         rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id);
2967         if (rc) {
2968                 BNXT_TF_DBG(ERR, "Failed to get the app id in glb init (%d).\n",
2969                             rc);
2970                 return rc;
2971         }
2972
2973         rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id);
2974         if (rc) {
2975                 BNXT_TF_DBG(ERR, "Failed to get dev id for app glb init (%d)\n",
2976                             rc);
2977                 return rc;
2978         }
2979
2980         /* Store all the app global resources */
2981         for (i = 0; i < num_entries; i++) {
2982                 if (dev_id != glb_res[i].device_id ||
2983                     app_id != glb_res[i].app_id)
2984                         continue;
2985                 dir = glb_res[i].direction;
2986                 res = glb_res[i].resource_type;
2987                 addend = 1;
2988
2989                 switch (glb_res[i].resource_func) {
2990                 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
2991                         res_info = &sparms.session_info.ident[dir].info[res];
2992                         break;
2993                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2994                         /*
2995                          * Tables may have various strides for the allocations.
2996                          * Need to account.
2997                          */
2998                         memset(&iparms, 0, sizeof(iparms));
2999                         iparms.dir = dir;
3000                         iparms.type = res;
3001                         rc = tf_get_shared_tbl_increment(tfp, &iparms);
3002                         if (rc) {
3003                                 BNXT_TF_DBG(ERR,
3004                                             "Failed to get addend for %s[%s] rc=(%d)\n",
3005                                             tf_tbl_type_2_str(res),
3006                                             tf_dir_2_str(dir), rc);
3007                                 return rc;
3008                         }
3009                         addend = iparms.increment_cnt;
3010                         res_info = &sparms.session_info.tbl[dir].info[res];
3011                         break;
3012                 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
3013                         res_info = &sparms.session_info.tcam[dir].info[res];
3014                         break;
3015                 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
3016                         res_info = &sparms.session_info.em[dir].info[res];
3017                         break;
3018                 default:
3019                         BNXT_TF_DBG(ERR, "Unknown resource func (0x%x)\n",
3020                                     glb_res[i].resource_func);
3021                         continue;
3022                 }
3023                 regval = tfp_cpu_to_be_64((uint64_t)res_info->start);
3024                 res_info->start += addend;
3025                 /*
3026                  * All resources written to the global regfile are shared for
3027                  * this function.
3028                  */
3029                 rc = ulp_mapper_glb_resource_write(mapper_data, &glb_res[i],
3030                                                    regval, true);
3031                 if (rc)
3032                         return rc;
3033         }
3034
3035         return rc;
3036 }
3037
3038 /*
3039  * Common conditional opcode process routine that is used for both the template
3040  * rejection and table conditional execution.
3041  */
3042 static int32_t
3043 ulp_mapper_cond_opc_process(struct bnxt_ulp_mapper_parms *parms,
3044                             enum bnxt_ulp_cond_opc opc,
3045                             uint32_t operand,
3046                             int32_t *res)
3047 {
3048         enum bnxt_ulp_flow_mem_type mtype = BNXT_ULP_FLOW_MEM_TYPE_INT;
3049         int32_t rc = 0;
3050         uint8_t bit;
3051         uint64_t regval;
3052
3053         switch (opc) {
3054         case BNXT_ULP_COND_OPC_CF_IS_SET:
3055                 if (operand < BNXT_ULP_CF_IDX_LAST) {
3056                         *res = ULP_COMP_FLD_IDX_RD(parms, operand);
3057                 } else {
3058                         BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
3059                                     operand);
3060                         rc = -EINVAL;
3061                 }
3062                 break;
3063         case BNXT_ULP_COND_OPC_CF_NOT_SET:
3064                 if (operand < BNXT_ULP_CF_IDX_LAST) {
3065                         *res = !ULP_COMP_FLD_IDX_RD(parms, operand);
3066                 } else {
3067                         BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
3068                                     operand);
3069                         rc = -EINVAL;
3070                 }
3071                 break;
3072         case BNXT_ULP_COND_OPC_ACT_BIT_IS_SET:
3073                 if (operand < BNXT_ULP_ACT_BIT_LAST) {
3074                         *res = ULP_BITMAP_ISSET(parms->act_bitmap->bits,
3075                                                 operand);
3076                 } else {
3077                         BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
3078                                     operand);
3079                         rc = -EINVAL;
3080                 }
3081                 break;
3082         case BNXT_ULP_COND_OPC_ACT_BIT_NOT_SET:
3083                 if (operand < BNXT_ULP_ACT_BIT_LAST) {
3084                         *res = !ULP_BITMAP_ISSET(parms->act_bitmap->bits,
3085                                                operand);
3086                 } else {
3087                         BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
3088                                     operand);
3089                         rc = -EINVAL;
3090                 }
3091                 break;
3092         case BNXT_ULP_COND_OPC_HDR_BIT_IS_SET:
3093                 if (operand < BNXT_ULP_HDR_BIT_LAST) {
3094                         *res = ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
3095                                                 operand);
3096                 } else {
3097                         BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
3098                                     operand);
3099                         rc = -EINVAL;
3100                 }
3101                 break;
3102         case BNXT_ULP_COND_OPC_HDR_BIT_NOT_SET:
3103                 if (operand < BNXT_ULP_HDR_BIT_LAST) {
3104                         *res = !ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
3105                                                operand);
3106                 } else {
3107                         BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
3108                                     operand);
3109                         rc = -EINVAL;
3110                 }
3111                 break;
3112         case BNXT_ULP_COND_OPC_FIELD_BIT_IS_SET:
3113                 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
3114                 if (rc) {
3115                         BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
3116                                     operand);
3117                         return -EINVAL;
3118                 }
3119                 *res = ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
3120                 break;
3121         case BNXT_ULP_COND_OPC_FIELD_BIT_NOT_SET:
3122                 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
3123                 if (rc) {
3124                         BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
3125                                     operand);
3126                         return -EINVAL;
3127                 }
3128                 *res = !ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
3129                 break;
3130         case BNXT_ULP_COND_OPC_RF_IS_SET:
3131                 if (!ulp_regfile_read(parms->regfile, operand, &regval)) {
3132                         BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
3133                         return -EINVAL;
3134                 }
3135                 *res = regval != 0;
3136                 break;
3137         case BNXT_ULP_COND_OPC_RF_NOT_SET:
3138                 if (!ulp_regfile_read(parms->regfile, operand, &regval)) {
3139                         BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
3140                         return -EINVAL;
3141                 }
3142                 *res = regval == 0;
3143                 break;
3144         case BNXT_ULP_COND_OPC_FLOW_PAT_MATCH:
3145                 if (parms->flow_pattern_id == operand) {
3146                         BNXT_TF_DBG(ERR, "field pattern match failed %x\n",
3147                                     parms->flow_pattern_id);
3148                         return -EINVAL;
3149                 }
3150                 break;
3151         case BNXT_ULP_COND_OPC_ACT_PAT_MATCH:
3152                 if (parms->act_pattern_id == operand) {
3153                         BNXT_TF_DBG(ERR, "act pattern match failed %x\n",
3154                                     parms->act_pattern_id);
3155                         return -EINVAL;
3156                 }
3157                 break;
3158         case BNXT_ULP_COND_OPC_EXT_MEM_IS_SET:
3159                 if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) {
3160                         BNXT_TF_DBG(ERR, "Failed to get the mem type\n");
3161                         return -EINVAL;
3162                 }
3163                 *res = (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) ? 0 : 1;
3164                 break;
3165         case BNXT_ULP_COND_OPC_EXT_MEM_NOT_SET:
3166                 if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) {
3167                         BNXT_TF_DBG(ERR, "Failed to get the mem type\n");
3168                         return -EINVAL;
3169                 }
3170                 *res = (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) ? 1 : 0;
3171                 break;
3172         default:
3173                 BNXT_TF_DBG(ERR, "Invalid conditional opcode %d\n", opc);
3174                 rc = -EINVAL;
3175                 break;
3176         }
3177         return (rc);
3178 }
3179
3180 static int32_t
3181 ulp_mapper_func_opr_compute(struct bnxt_ulp_mapper_parms *parms,
3182                             enum tf_dir dir,
3183                             enum bnxt_ulp_func_src func_src,
3184                             uint16_t func_opr,
3185                             uint64_t *result)
3186 {
3187         uint64_t regval;
3188         bool shared;
3189
3190         *result =  false;
3191         switch (func_src) {
3192         case BNXT_ULP_FUNC_SRC_COMP_FIELD:
3193                 if (func_opr >= BNXT_ULP_CF_IDX_LAST) {
3194                         BNXT_TF_DBG(ERR, "invalid index %u\n", func_opr);
3195                         return -EINVAL;
3196                 }
3197                 *result = ULP_COMP_FLD_IDX_RD(parms, func_opr);
3198                 break;
3199         case BNXT_ULP_FUNC_SRC_REGFILE:
3200                 if (!ulp_regfile_read(parms->regfile, func_opr, &regval)) {
3201                         BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", func_opr);
3202                         return -EINVAL;
3203                 }
3204                 *result = tfp_be_to_cpu_64(regval);
3205                 break;
3206         case BNXT_ULP_FUNC_SRC_GLB_REGFILE:
3207                 if (ulp_mapper_glb_resource_read(parms->mapper_data, dir,
3208                                                  func_opr, &regval, &shared)) {
3209                         BNXT_TF_DBG(ERR, "global regfile[%d] read failed.\n",
3210                                     func_opr);
3211                         return -EINVAL;
3212                 }
3213                 *result = tfp_be_to_cpu_64(regval);
3214                 break;
3215         case BNXT_ULP_FUNC_SRC_CONST:
3216                 *result = func_opr;
3217                 break;
3218         default:
3219                 BNXT_TF_DBG(ERR, "invalid src code %u\n", func_src);
3220                 return -EINVAL;
3221         }
3222         return 0;
3223 }
3224
3225 static int32_t
3226 ulp_mapper_func_info_process(struct bnxt_ulp_mapper_parms *parms,
3227                              struct bnxt_ulp_mapper_tbl_info *tbl)
3228 {
3229         struct bnxt_ulp_mapper_func_info *func_info = &tbl->func_info;
3230         uint64_t res = 0, res1 = 0, res2 = 0;
3231         int32_t rc = 0;
3232         uint32_t process_src1 = 0, process_src2 = 0;
3233
3234         /* determine which functional operands to compute */
3235         switch (func_info->func_opc) {
3236         case BNXT_ULP_FUNC_OPC_NOP:
3237                 return rc;
3238         case BNXT_ULP_FUNC_OPC_EQ:
3239         case BNXT_ULP_FUNC_OPC_NE:
3240         case BNXT_ULP_FUNC_OPC_GE:
3241         case BNXT_ULP_FUNC_OPC_GT:
3242         case BNXT_ULP_FUNC_OPC_LE:
3243         case BNXT_ULP_FUNC_OPC_LT:
3244                 process_src1 = 1;
3245                 process_src2 = 1;
3246                 break;
3247         case BNXT_ULP_FUNC_OPC_COPY_SRC1_TO_RF:
3248                 process_src1 = 1;
3249                 break;
3250         default:
3251                 break;
3252         }
3253
3254         if (process_src1) {
3255                 rc = ulp_mapper_func_opr_compute(parms, tbl->direction,
3256                                                  func_info->func_src1,
3257                                                  func_info->func_opr1, &res1);
3258                 if (rc)
3259                         return rc;
3260         }
3261
3262         if (process_src2) {
3263                 rc = ulp_mapper_func_opr_compute(parms, tbl->direction,
3264                                                  func_info->func_src2,
3265                                                  func_info->func_opr2, &res2);
3266                 if (rc)
3267                         return rc;
3268         }
3269
3270         /* perform the functional opcode operations */
3271         switch (func_info->func_opc) {
3272         case BNXT_ULP_FUNC_OPC_EQ:
3273                 if (res1 == res2)
3274                         res = 1;
3275                 break;
3276         case BNXT_ULP_FUNC_OPC_NE:
3277                 if (res1 != res2)
3278                         res = 1;
3279                 break;
3280         case BNXT_ULP_FUNC_OPC_GE:
3281                 if (res1 >= res2)
3282                         res = 1;
3283                 break;
3284         case BNXT_ULP_FUNC_OPC_GT:
3285                 if (res1 > res2)
3286                         res = 1;
3287                 break;
3288         case BNXT_ULP_FUNC_OPC_LE:
3289                 if (res1 <= res2)
3290                         res = 1;
3291                 break;
3292         case BNXT_ULP_FUNC_OPC_LT:
3293                 if (res1 < res2)
3294                         res = 1;
3295                 break;
3296         case BNXT_ULP_FUNC_OPC_COPY_SRC1_TO_RF:
3297                 res = res1;
3298                 break;
3299         case BNXT_ULP_FUNC_OPC_RSS_CONFIG:
3300                 /* apply the rss config using pmd method */
3301                 return bnxt_rss_config_action_apply(parms);
3302         case BNXT_ULP_FUNC_OPC_GET_PARENT_MAC_ADDR:
3303                 rc = bnxt_pmd_get_parent_mac_addr(parms, (uint8_t *)&res);
3304                 if (rc)
3305                         return -EINVAL;
3306                 res = tfp_be_to_cpu_64(res);
3307                 break;
3308         default:
3309                 BNXT_TF_DBG(ERR, "invalid func code %u\n", func_info->func_opc);
3310                 return -EINVAL;
3311         }
3312         if (ulp_regfile_write(parms->regfile, func_info->func_dst_opr,
3313                               tfp_cpu_to_be_64(res))) {
3314                 BNXT_TF_DBG(ERR, "Failed write the func_opc %u\n",
3315                             func_info->func_dst_opr);
3316                 return -EINVAL;
3317         }
3318
3319         return rc;
3320 }
3321
3322
3323 /*
3324  * Processes a list of conditions and returns both a status and result of the
3325  * list.  The status must be checked prior to verifying the result.
3326  *
3327  * returns 0 for success, negative on failure
3328  * returns res = 1 for true, res = 0 for false.
3329  */
3330 static int32_t
3331 ulp_mapper_cond_opc_list_process(struct bnxt_ulp_mapper_parms *parms,
3332                                  enum bnxt_ulp_cond_list_opc list_opc,
3333                                  struct bnxt_ulp_mapper_cond_info *list,
3334                                  uint32_t num,
3335                                  int32_t *res)
3336 {
3337         uint32_t i;
3338         int32_t rc = 0, trc = 0;
3339
3340         switch (list_opc) {
3341         case BNXT_ULP_COND_LIST_OPC_AND:
3342                 /* AND Defaults to true. */
3343                 *res = 1;
3344                 break;
3345         case BNXT_ULP_COND_LIST_OPC_OR:
3346                 /* OR Defaults to false. */
3347                 *res = 0;
3348                 break;
3349         case BNXT_ULP_COND_LIST_OPC_TRUE:
3350                 *res = 1;
3351                 return rc;
3352         case BNXT_ULP_COND_LIST_OPC_FALSE:
3353                 *res = 0;
3354                 return rc;
3355         default:
3356                 BNXT_TF_DBG(ERR, "Invalid conditional list opcode %d\n",
3357                             list_opc);
3358                 *res = 0;
3359                 return -EINVAL;
3360         }
3361
3362         for (i = 0; i < num; i++) {
3363                 rc = ulp_mapper_cond_opc_process(parms,
3364                                                  list[i].cond_opcode,
3365                                                  list[i].cond_operand,
3366                                                  &trc);
3367                 if (rc)
3368                         return rc;
3369
3370                 if (list_opc == BNXT_ULP_COND_LIST_OPC_AND) {
3371                         /* early return if result is ever zero */
3372                         if (!trc) {
3373                                 *res = trc;
3374                                 return rc;
3375                         }
3376                 } else {
3377                         /* early return if result is ever non-zero */
3378                         if (trc) {
3379                                 *res = trc;
3380                                 return rc;
3381                         }
3382                 }
3383         }
3384
3385         return rc;
3386 }
3387
3388 /*
3389  * Processes conflict resolution and returns both a status and result.
3390  * The status must be checked prior to verifying the result.
3391  *
3392  * returns 0 for success, negative on failure
3393  * returns res = 1 for true, res = 0 for false.
3394  */
3395 static int32_t
3396 ulp_mapper_conflict_resolution_process(struct bnxt_ulp_mapper_parms *parms,
3397                                        struct bnxt_ulp_mapper_tbl_info *tbl,
3398                                        int32_t *res)
3399 {
3400         int32_t rc = 0;
3401         uint64_t regval;
3402         uint64_t comp_sig;
3403
3404         *res = 0;
3405         switch (tbl->accept_opcode) {
3406         case BNXT_ULP_ACCEPT_OPC_ALWAYS:
3407                 *res = 1;
3408                 break;
3409         case BNXT_ULP_ACCEPT_OPC_FLOW_SIG_ID_MATCH:
3410                 /* perform the signature validation*/
3411                 if (tbl->resource_func ==
3412                     BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE) {
3413                         /* Perform the check that generic table is hit or not */
3414                         if (!ulp_regfile_read(parms->regfile,
3415                                               BNXT_ULP_RF_IDX_GENERIC_TBL_MISS,
3416                                               &regval)) {
3417                                 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
3418                                             BNXT_ULP_RF_IDX_GENERIC_TBL_MISS);
3419                                 return -EINVAL;
3420                         }
3421                         if (regval) {
3422                                 /* not a hit so no need to check flow sign*/
3423                                 *res = 1;
3424                                 return rc;
3425                         }
3426                 }
3427                 /* compare the new flow signature against stored one */
3428                 if (!ulp_regfile_read(parms->regfile,
3429                                       BNXT_ULP_RF_IDX_FLOW_SIG_ID,
3430                                       &regval)) {
3431                         BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
3432                                     BNXT_ULP_RF_IDX_FLOW_SIG_ID);
3433                         return -EINVAL;
3434                 }
3435                 comp_sig = ULP_COMP_FLD_IDX_RD(parms,
3436                                                BNXT_ULP_CF_IDX_FLOW_SIG_ID);
3437                 regval = tfp_be_to_cpu_64(regval);
3438                 if (comp_sig == regval)
3439                         *res = 1;
3440                 else
3441                         BNXT_TF_DBG(ERR, "failed signature match 0x%016"
3442                                     PRIX64 ":%x\n", comp_sig, (uint32_t)regval);
3443                 break;
3444         default:
3445                 BNXT_TF_DBG(ERR, "Invalid accept opcode %d\n",
3446                             tbl->accept_opcode);
3447                 return -EINVAL;
3448         }
3449         return rc;
3450 }
3451
3452 static int32_t
3453 ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid)
3454 {
3455         struct bnxt_ulp_mapper_cond_info *cond_tbls = NULL;
3456         enum bnxt_ulp_cond_list_opc cond_opc;
3457         struct bnxt_ulp_mapper_tbl_info *tbls;
3458         struct bnxt_ulp_mapper_tbl_info *tbl;
3459         uint32_t num_tbls, tbl_idx, num_cond_tbls;
3460         int32_t rc = -EINVAL, cond_rc = 0;
3461         int32_t cond_goto = 1;
3462
3463         cond_tbls = ulp_mapper_tmpl_reject_list_get(parms, tid,
3464                                                     &num_cond_tbls,
3465                                                     &cond_opc);
3466         /*
3467          * Process the reject list if exists, otherwise assume that the
3468          * template is allowed.
3469          */
3470         if (cond_tbls && num_cond_tbls) {
3471                 rc = ulp_mapper_cond_opc_list_process(parms,
3472                                                       cond_opc,
3473                                                       cond_tbls,
3474                                                       num_cond_tbls,
3475                                                       &cond_rc);
3476                 if (rc)
3477                         return rc;
3478
3479                 /* Reject the template if True */
3480                 if (cond_rc) {
3481                         BNXT_TF_DBG(ERR, "%s Template %d rejected.\n",
3482                                     ulp_mapper_tmpl_name_str(parms->tmpl_type),
3483                                     tid);
3484                         return -EINVAL;
3485                 }
3486         }
3487
3488         tbls = ulp_mapper_tbl_list_get(parms, tid, &num_tbls);
3489         if (!tbls || !num_tbls) {
3490                 BNXT_TF_DBG(ERR, "No %s tables for %d:%d\n",
3491                             ulp_mapper_tmpl_name_str(parms->tmpl_type),
3492                             parms->dev_id, tid);
3493                 return -EINVAL;
3494         }
3495
3496         for (tbl_idx = 0; tbl_idx < num_tbls && cond_goto;) {
3497                 tbl = &tbls[tbl_idx];
3498                 cond_goto = tbl->execute_info.cond_true_goto;
3499                 /* Process the conditional func code opcodes */
3500                 if (ulp_mapper_func_info_process(parms, tbl)) {
3501                         BNXT_TF_DBG(ERR, "Failed to process cond update\n");
3502                         rc = -EINVAL;
3503                         goto error;
3504                 }
3505
3506                 cond_tbls = ulp_mapper_tbl_execute_list_get(parms, tbl,
3507                                                             &num_cond_tbls,
3508                                                             &cond_opc);
3509                 rc = ulp_mapper_cond_opc_list_process(parms, cond_opc,
3510                                                       cond_tbls, num_cond_tbls,
3511                                                       &cond_rc);
3512                 if (rc) {
3513                         BNXT_TF_DBG(ERR, "Failed to proc cond opc list (%d)\n",
3514                                     rc);
3515                         goto error;
3516                 }
3517                 /* Skip the table if False */
3518                 if (!cond_rc) {
3519                         cond_goto = tbl->execute_info.cond_false_goto;
3520                         goto next_iteration;
3521                 }
3522
3523                 switch (tbl->resource_func) {
3524                 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
3525                         rc = ulp_mapper_tcam_tbl_process(parms, tbl);
3526                         break;
3527                 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
3528                         rc = ulp_mapper_em_tbl_process(parms, tbl);
3529                         break;
3530                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3531                         rc = ulp_mapper_index_tbl_process(parms, tbl);
3532                         break;
3533                 case BNXT_ULP_RESOURCE_FUNC_IF_TABLE:
3534                         rc = ulp_mapper_if_tbl_process(parms, tbl);
3535                         break;
3536                 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
3537                         rc = ulp_mapper_gen_tbl_process(parms, tbl);
3538                         break;
3539                 case BNXT_ULP_RESOURCE_FUNC_CTRL_TABLE:
3540                         rc = ulp_mapper_ctrl_tbl_process(parms, tbl);
3541                         break;
3542                 case BNXT_ULP_RESOURCE_FUNC_INVALID:
3543                         rc = 0;
3544                         break;
3545                 default:
3546                         BNXT_TF_DBG(ERR, "Unexpected mapper resource %d\n",
3547                                     tbl->resource_func);
3548                         rc = -EINVAL;
3549                         goto error;
3550                 }
3551
3552                 if (rc) {
3553                         BNXT_TF_DBG(ERR, "Resource type %d failed\n",
3554                                     tbl->resource_func);
3555                         goto error;
3556                 }
3557
3558                 /* perform the post table process */
3559                 rc  = ulp_mapper_conflict_resolution_process(parms, tbl,
3560                                                              &cond_rc);
3561                 if (rc || !cond_rc) {
3562                         BNXT_TF_DBG(ERR, "Failed due to conflict resolution\n");
3563                         rc = -EINVAL;
3564                         goto error;
3565                 }
3566 next_iteration:
3567                 if (cond_goto == BNXT_ULP_COND_GOTO_REJECT) {
3568                         BNXT_TF_DBG(ERR, "reject the flow\n");
3569                         rc = -EINVAL;
3570                         goto error;
3571                 } else if (cond_goto & BNXT_ULP_COND_GOTO_RF) {
3572                         uint32_t rf_idx;
3573                         uint64_t regval;
3574
3575                         /* least significant 16 bits from reg_file index */
3576                         rf_idx = (uint32_t)(cond_goto & 0xFFFF);
3577                         if (!ulp_regfile_read(parms->regfile, rf_idx,
3578                                               &regval)) {
3579                                 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
3580                                             rf_idx);
3581                                 rc = -EINVAL;
3582                                 goto error;
3583                         }
3584                         cond_goto = (int32_t)regval;
3585                 }
3586
3587                 if (cond_goto < 0 && ((int32_t)tbl_idx + cond_goto) < 0) {
3588                         BNXT_TF_DBG(ERR, "invalid conditional goto %d\n",
3589                                     cond_goto);
3590                         goto error;
3591                 }
3592                 tbl_idx += cond_goto;
3593         }
3594
3595         return rc;
3596 error:
3597         BNXT_TF_DBG(ERR, "%s tables failed creation for %d:%d\n",
3598                     ulp_mapper_tmpl_name_str(parms->tmpl_type),
3599                     parms->dev_id, tid);
3600         return rc;
3601 }
3602
3603 static int32_t
3604 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
3605                          uint32_t fid,
3606                          struct ulp_flow_db_res_params *res)
3607 {
3608         struct tf *tfp;
3609         int32_t rc = 0;
3610
3611         if (!res || !ulp) {
3612                 BNXT_TF_DBG(ERR, "Unable to free resource\n ");
3613                 return -EINVAL;
3614         }
3615         if (res->fdb_flags & ULP_FDB_FLAG_SHARED_SESSION)
3616                 tfp = bnxt_ulp_cntxt_tfp_get(ulp, BNXT_ULP_SHARED_SESSION_YES);
3617         else
3618                 tfp = bnxt_ulp_cntxt_tfp_get(ulp, BNXT_ULP_SHARED_SESSION_NO);
3619         if (!tfp) {
3620                 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
3621                 return -EINVAL;
3622         }
3623
3624         switch (res->resource_func) {
3625         case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
3626                 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
3627                 break;
3628         case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
3629                 rc = ulp_mapper_em_entry_free(ulp, tfp, res);
3630                 break;
3631         case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3632                 rc = ulp_mapper_index_entry_free(ulp, tfp, res);
3633                 break;
3634         case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
3635                 rc = ulp_mapper_ident_free(ulp, tfp, res);
3636                 break;
3637         case BNXT_ULP_RESOURCE_FUNC_HW_FID:
3638                 rc = ulp_mapper_mark_free(ulp, res);
3639                 break;
3640         case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW:
3641                 rc = ulp_mapper_parent_flow_free(ulp, fid, res);
3642                 break;
3643         case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW:
3644                 rc = ulp_mapper_child_flow_free(ulp, fid, res);
3645                 break;
3646         case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
3647                 rc = ulp_mapper_gen_tbl_res_free(ulp, res);
3648                 break;
3649         default:
3650                 break;
3651         }
3652
3653         return rc;
3654 }
3655
3656 int32_t
3657 ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx,
3658                           enum bnxt_ulp_fdb_type flow_type,
3659                           uint32_t fid)
3660 {
3661         struct ulp_flow_db_res_params res_parms = { 0 };
3662         int32_t rc, trc;
3663
3664         if (!ulp_ctx) {
3665                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
3666                 return -EINVAL;
3667         }
3668
3669         /*
3670          * Set the critical resource on the first resource del, then iterate
3671          * while status is good
3672          */
3673         if (flow_type != BNXT_ULP_FDB_TYPE_RID)
3674                 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES;
3675
3676         rc = ulp_flow_db_resource_del(ulp_ctx, flow_type, fid, &res_parms);
3677
3678         if (rc) {
3679                 /*
3680                  * This is unexpected on the first call to resource del.
3681                  * It likely means that the flow did not exist in the flow db.
3682                  */
3683                 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
3684                             flow_type, fid, rc);
3685                 return rc;
3686         }
3687
3688         while (!rc) {
3689                 trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms);
3690                 if (trc)
3691                         /*
3692                          * On fail, we still need to attempt to free the
3693                          * remaining resources.  Don't return
3694                          */
3695                         BNXT_TF_DBG(ERR,
3696                                     "Flow[%d][0x%x] Res[%d][0x%016" PRIX64
3697                                     "] failed rc=%d.\n",
3698                                     flow_type, fid, res_parms.resource_func,
3699                                     res_parms.resource_hndl, trc);
3700
3701                 /* All subsequent call require the non-critical_resource */
3702                 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
3703
3704                 rc = ulp_flow_db_resource_del(ulp_ctx,
3705                                               flow_type,
3706                                               fid,
3707                                               &res_parms);
3708         }
3709
3710         /* Free the Flow ID since we've removed all resources */
3711         rc = ulp_flow_db_fid_free(ulp_ctx, flow_type, fid);
3712
3713         return rc;
3714 }
3715
3716 static void
3717 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx,
3718                                     struct bnxt_ulp_mapper_data *mapper_data)
3719 {
3720         struct bnxt_ulp_mapper_glb_resource_entry *ent;
3721         struct ulp_flow_db_res_params res;
3722         uint32_t dir, idx;
3723
3724         /* Iterate the global resources and process each one */
3725         for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) {
3726                 for (idx = 0; idx < BNXT_ULP_GLB_RF_IDX_LAST; idx++) {
3727                         ent = &mapper_data->glb_res_tbl[dir][idx];
3728                         if (ent->resource_func ==
3729                             BNXT_ULP_RESOURCE_FUNC_INVALID ||
3730                             ent->shared)
3731                                 continue;
3732                         memset(&res, 0, sizeof(struct ulp_flow_db_res_params));
3733                         res.resource_func = ent->resource_func;
3734                         res.direction = dir;
3735                         res.resource_type = ent->resource_type;
3736                         /*convert it from BE to cpu */
3737                         res.resource_hndl =
3738                                 tfp_be_to_cpu_64(ent->resource_hndl);
3739                         ulp_mapper_resource_free(ulp_ctx, 0, &res);
3740                 }
3741         }
3742 }
3743
3744 int32_t
3745 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx,
3746                         enum bnxt_ulp_fdb_type flow_type,
3747                         uint32_t fid)
3748 {
3749         int32_t rc;
3750
3751         if (!ulp_ctx) {
3752                 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
3753                 return -EINVAL;
3754         }
3755
3756         rc = ulp_mapper_resources_free(ulp_ctx, flow_type, fid);
3757         return rc;
3758 }
3759
3760 /* Function to handle the mapping of the Flow to be compatible
3761  * with the underlying hardware.
3762  */
3763 int32_t
3764 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
3765                        struct bnxt_ulp_mapper_create_parms *cparms)
3766 {
3767         struct bnxt_ulp_mapper_parms parms;
3768         struct ulp_regfile regfile;
3769         int32_t  rc = 0, trc;
3770
3771         if (!ulp_ctx || !cparms)
3772                 return -EINVAL;
3773
3774         /* Initialize the parms structure */
3775         memset(&parms, 0, sizeof(parms));
3776         parms.act_prop = cparms->act_prop;
3777         parms.act_bitmap = cparms->act;
3778         parms.hdr_bitmap = cparms->hdr_bitmap;
3779         parms.regfile = &regfile;
3780         parms.hdr_field = cparms->hdr_field;
3781         parms.fld_bitmap = cparms->fld_bitmap;
3782         parms.comp_fld = cparms->comp_fld;
3783         parms.ulp_ctx = ulp_ctx;
3784         parms.act_tid = cparms->act_tid;
3785         parms.class_tid = cparms->class_tid;
3786         parms.flow_type = cparms->flow_type;
3787         parms.parent_flow = cparms->parent_flow;
3788         parms.parent_fid = cparms->parent_fid;
3789         parms.fid = cparms->flow_id;
3790         parms.tun_idx = cparms->tun_idx;
3791         parms.app_priority = cparms->app_priority;
3792         parms.flow_pattern_id = cparms->flow_pattern_id;
3793         parms.act_pattern_id = cparms->act_pattern_id;
3794         parms.app_id = cparms->app_id;
3795         parms.port_id = cparms->port_id;
3796
3797         /* Get the device id from the ulp context */
3798         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
3799                 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
3800                 return -EINVAL;
3801         }
3802
3803         /* Get the device params, it will be used in later processing */
3804         parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
3805         if (!parms.device_params) {
3806                 BNXT_TF_DBG(ERR, "No device parms for device id %d\n",
3807                             parms.dev_id);
3808                 return -EINVAL;
3809         }
3810
3811         /*
3812          * Get the mapper data for dynamic mapper data such as default
3813          * ids.
3814          */
3815         parms.mapper_data = (struct bnxt_ulp_mapper_data *)
3816                 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3817         if (!parms.mapper_data) {
3818                 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
3819                 return -EINVAL;
3820         }
3821
3822         /* initialize the registry file for further processing */
3823         if (!ulp_regfile_init(parms.regfile)) {
3824                 BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
3825                 return -EINVAL;
3826         }
3827
3828         /* Process the action template list from the selected action table*/
3829         if (parms.act_tid) {
3830                 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_ACTION;
3831                 /* Process the action template tables */
3832                 rc = ulp_mapper_tbls_process(&parms, parms.act_tid);
3833                 if (rc)
3834                         goto flow_error;
3835                 cparms->shared_hndl = parms.shared_hndl;
3836         }
3837
3838         if (parms.class_tid) {
3839                 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
3840
3841                 /* Process the class template tables.*/
3842                 rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
3843                 if (rc)
3844                         goto flow_error;
3845         }
3846
3847         /* setup the parent-child details */
3848         if (parms.parent_flow) {
3849                 /* create a parent flow details */
3850                 rc = ulp_flow_db_parent_flow_create(&parms);
3851                 if (rc)
3852                         goto flow_error;
3853         } else if (parms.parent_fid) {
3854                 /* create a child flow details */
3855                 rc = ulp_flow_db_child_flow_create(&parms);
3856                 if (rc)
3857                         goto flow_error;
3858         }
3859
3860         return rc;
3861
3862 flow_error:
3863         /* Free all resources that were allocated during flow creation */
3864         trc = ulp_mapper_flow_destroy(ulp_ctx, parms.flow_type,
3865                                       parms.fid);
3866         if (trc)
3867                 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
3868
3869         return rc;
3870 }
3871
3872 int32_t
3873 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx)
3874 {
3875         struct bnxt_ulp_mapper_data *data;
3876         struct tf *tfp;
3877         int32_t rc;
3878
3879         if (!ulp_ctx)
3880                 return -EINVAL;
3881
3882         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO);
3883         if (!tfp)
3884                 return -EINVAL;
3885
3886         data = rte_zmalloc("ulp_mapper_data",
3887                            sizeof(struct bnxt_ulp_mapper_data), 0);
3888         if (!data) {
3889                 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n");
3890                 return -ENOMEM;
3891         }
3892
3893         if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) {
3894                 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n");
3895                 /* Don't call deinit since the prof_func wasn't allocated. */
3896                 rte_free(data);
3897                 return -ENOMEM;
3898         }
3899
3900         /* Allocate the global resource ids */
3901         rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data);
3902         if (rc) {
3903                 BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n");
3904                 goto error;
3905         }
3906
3907         /*
3908          * Only initialize the app global resources if a shared session was
3909          * created.
3910          */
3911         if (bnxt_ulp_cntxt_shared_session_enabled(ulp_ctx)) {
3912                 rc = ulp_mapper_app_glb_resource_info_init(ulp_ctx, data);
3913                 if (rc) {
3914                         BNXT_TF_DBG(ERR, "Failed to init app glb resources\n");
3915                         goto error;
3916                 }
3917         }
3918
3919         /* Allocate the generic table list */
3920         rc = ulp_mapper_generic_tbl_list_init(data);
3921         if (rc) {
3922                 BNXT_TF_DBG(ERR, "Failed to initialize generic tbl list\n");
3923                 goto error;
3924         }
3925
3926         return 0;
3927 error:
3928         /* Ignore the return code in favor of returning the original error. */
3929         ulp_mapper_deinit(ulp_ctx);
3930         return rc;
3931 }
3932
3933 void
3934 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx)
3935 {
3936         struct bnxt_ulp_mapper_data *data;
3937         struct tf *tfp;
3938
3939         if (!ulp_ctx) {
3940                 BNXT_TF_DBG(ERR,
3941                             "Failed to acquire ulp context, so data may not be released.\n");
3942                 return;
3943         }
3944
3945         data = (struct bnxt_ulp_mapper_data *)
3946                 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3947         if (!data) {
3948                 /* Go ahead and return since there is no allocated data. */
3949                 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n");
3950                 return;
3951         }
3952
3953         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO);
3954         if (!tfp) {
3955                 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n");
3956                 /* Free the mapper data regardless of errors. */
3957                 goto free_mapper_data;
3958         }
3959
3960         /* Free the global resource info table entries */
3961         ulp_mapper_glb_resource_info_deinit(ulp_ctx, data);
3962
3963 free_mapper_data:
3964         /* Free the generic table */
3965         (void)ulp_mapper_generic_tbl_list_deinit(data);
3966
3967         rte_free(data);
3968         /* Reset the data pointer within the ulp_ctx. */
3969         bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL);
3970 }