1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2014-2021 Broadcom
7 #include <rte_malloc.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"
15 #include "tf_ext_flow_handle.h"
16 #include "ulp_mark_mgr.h"
17 #include "ulp_mapper.h"
18 #include "ulp_flow_db.h"
20 #include "ulp_template_db_tbl.h"
21 #include "ulp_port_db.h"
23 static uint8_t mapper_fld_ones[16] = {
24 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
25 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
29 ulp_mapper_tmpl_name_str(enum bnxt_ulp_template_type tmpl_type)
32 case BNXT_ULP_TEMPLATE_TYPE_CLASS:
34 case BNXT_ULP_TEMPLATE_TYPE_ACTION:
37 return "invalid template type";
42 static struct bnxt_ulp_glb_resource_info *
43 ulp_mapper_glb_resource_info_list_get(uint32_t *num_entries)
47 *num_entries = BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
48 return ulp_glb_resource_tbl;
52 * Read the global resource from the mapper global resource list
54 * The regval is always returned in big-endian.
56 * returns 0 on success
59 ulp_mapper_glb_resource_read(struct bnxt_ulp_mapper_data *mapper_data,
64 if (!mapper_data || !regval ||
65 dir >= TF_DIR_MAX || idx >= BNXT_ULP_GLB_RF_IDX_LAST)
68 *regval = mapper_data->glb_res_tbl[dir][idx].resource_hndl;
73 * Write a global resource to the mapper global resource list
75 * The regval value must be in big-endian.
77 * return 0 on success.
80 ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data *data,
81 struct bnxt_ulp_glb_resource_info *res,
84 struct bnxt_ulp_mapper_glb_resource_entry *ent;
86 /* validate the arguments */
87 if (!data || res->direction >= TF_DIR_MAX ||
88 res->glb_regfile_index >= BNXT_ULP_GLB_RF_IDX_LAST)
91 /* write to the mapper data */
92 ent = &data->glb_res_tbl[res->direction][res->glb_regfile_index];
93 ent->resource_func = res->resource_func;
94 ent->resource_type = res->resource_type;
95 ent->resource_hndl = regval;
100 * Internal function to allocate identity resource and store it in mapper data.
102 * returns 0 on success
105 ulp_mapper_resource_ident_allocate(struct bnxt_ulp_context *ulp_ctx,
106 struct bnxt_ulp_mapper_data *mapper_data,
107 struct bnxt_ulp_glb_resource_info *glb_res)
109 struct tf_alloc_identifier_parms iparms = { 0 };
110 struct tf_free_identifier_parms fparms;
115 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
119 iparms.ident_type = glb_res->resource_type;
120 iparms.dir = glb_res->direction;
122 /* Allocate the Identifier using tf api */
123 rc = tf_alloc_identifier(tfp, &iparms);
125 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
126 tf_dir_2_str(iparms.dir),
131 /* entries are stored as big-endian format */
132 regval = tfp_cpu_to_be_64((uint64_t)iparms.id);
133 /* write to the mapper global resource */
134 rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval);
136 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
137 /* Free the identifier when update failed */
138 fparms.dir = iparms.dir;
139 fparms.ident_type = iparms.ident_type;
140 fparms.id = iparms.id;
141 tf_free_identifier(tfp, &fparms);
148 * Internal function to allocate index tbl resource and store it in mapper data.
150 * returns 0 on success
153 ulp_mapper_resource_index_tbl_alloc(struct bnxt_ulp_context *ulp_ctx,
154 struct bnxt_ulp_mapper_data *mapper_data,
155 struct bnxt_ulp_glb_resource_info *glb_res)
157 struct tf_alloc_tbl_entry_parms aparms = { 0 };
158 struct tf_free_tbl_entry_parms free_parms = { 0 };
161 uint32_t tbl_scope_id;
164 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
168 /* Get the scope id */
169 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &tbl_scope_id);
171 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
175 aparms.type = glb_res->resource_type;
176 aparms.dir = glb_res->direction;
177 aparms.search_enable = 0;
178 aparms.tbl_scope_id = tbl_scope_id;
180 /* Allocate the index tbl using tf api */
181 rc = tf_alloc_tbl_entry(tfp, &aparms);
183 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
184 tf_dir_2_str(aparms.dir), aparms.type);
188 /* entries are stored as big-endian format */
189 regval = tfp_cpu_to_be_64((uint64_t)aparms.idx);
190 /* write to the mapper global resource */
191 rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval);
193 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
194 /* Free the identifier when update failed */
195 free_parms.dir = aparms.dir;
196 free_parms.type = aparms.type;
197 free_parms.idx = aparms.idx;
198 tf_free_tbl_entry(tfp, &free_parms);
204 /* Retrieve the global template table */
206 ulp_mapper_glb_template_table_get(uint32_t *num_entries)
210 *num_entries = BNXT_ULP_GLB_TEMPLATE_TBL_MAX_SZ;
211 return ulp_glb_template_tbl;
215 ulp_mapper_glb_field_tbl_get(struct bnxt_ulp_mapper_parms *parms,
221 t_idx = parms->class_tid << (BNXT_ULP_HDR_SIG_ID_SHIFT +
222 BNXT_ULP_GLB_FIELD_TBL_SHIFT);
223 t_idx += ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_HDR_SIG_ID) <<
224 BNXT_ULP_GLB_FIELD_TBL_SHIFT;
227 if (t_idx >= BNXT_ULP_GLB_FIELD_TBL_SIZE) {
228 BNXT_TF_DBG(ERR, "Invalid hdr field index %x:%x:%x\n",
229 parms->class_tid, t_idx, operand);
231 return -EINVAL; /* error */
233 *val = ulp_glb_field_tbl[t_idx];
238 * Get the size of the action property for a given index.
240 * idx [in] The index for the action property
242 * returns the size of the action property.
245 ulp_mapper_act_prop_size_get(uint32_t idx)
247 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST)
249 return ulp_act_prop_map_table[idx];
252 static struct bnxt_ulp_mapper_cond_info *
253 ulp_mapper_tmpl_reject_list_get(struct bnxt_ulp_mapper_parms *mparms,
256 enum bnxt_ulp_cond_list_opc *opc)
259 const struct bnxt_ulp_template_device_tbls *dev_tbls;
261 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
262 *num_tbls = dev_tbls->tmpl_list[tid].reject_info.cond_nums;
263 *opc = dev_tbls->tmpl_list[tid].reject_info.cond_list_opcode;
264 idx = dev_tbls->tmpl_list[tid].reject_info.cond_start_idx;
266 return &dev_tbls->cond_list[idx];
269 static struct bnxt_ulp_mapper_cond_info *
270 ulp_mapper_tbl_execute_list_get(struct bnxt_ulp_mapper_parms *mparms,
271 struct bnxt_ulp_mapper_tbl_info *tbl,
273 enum bnxt_ulp_cond_list_opc *opc)
276 const struct bnxt_ulp_template_device_tbls *dev_tbls;
278 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
279 *num_tbls = tbl->execute_info.cond_nums;
280 *opc = tbl->execute_info.cond_list_opcode;
281 idx = tbl->execute_info.cond_start_idx;
283 return &dev_tbls->cond_list[idx];
287 * Get a list of classifier tables that implement the flow
288 * Gets a device dependent list of tables that implement the class template id
290 * mparms [in] The mappers parms with data related to the flow.
292 * tid [in] The template id that matches the flow
294 * num_tbls [out] The number of classifier tables in the returned array
296 * returns An array of classifier tables to implement the flow, or NULL on
299 static struct bnxt_ulp_mapper_tbl_info *
300 ulp_mapper_tbl_list_get(struct bnxt_ulp_mapper_parms *mparms,
305 const struct bnxt_ulp_template_device_tbls *dev_tbls;
307 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
309 idx = dev_tbls->tmpl_list[tid].start_tbl_idx;
310 *num_tbls = dev_tbls->tmpl_list[tid].num_tbls;
312 return &dev_tbls->tbl_list[idx];
316 * Get the list of key fields that implement the flow.
318 * mparms [in] The mapper parms with information about the flow
320 * tbl [in] A single table instance to get the key fields from
322 * num_flds [out] The number of key fields in the returned array
324 * Returns array of Key fields, or NULL on error.
326 static struct bnxt_ulp_mapper_key_info *
327 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_parms *mparms,
328 struct bnxt_ulp_mapper_tbl_info *tbl,
332 const struct bnxt_ulp_template_device_tbls *dev_tbls;
334 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
335 if (!dev_tbls->key_info_list) {
340 idx = tbl->key_start_idx;
341 *num_flds = tbl->key_num_fields;
343 return &dev_tbls->key_info_list[idx];
347 * Get the list of data fields that implement the flow.
349 * mparms [in] The mapper parms with information about the flow
351 * tbl [in] A single table instance to get the data fields from
353 * num_flds [out] The number of data fields in the returned array.
355 * num_encap_flds [out] The number of encap fields in the returned array.
357 * Returns array of data fields, or NULL on error.
359 static struct bnxt_ulp_mapper_field_info *
360 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_parms *mparms,
361 struct bnxt_ulp_mapper_tbl_info *tbl,
363 uint32_t *num_encap_flds)
366 const struct bnxt_ulp_template_device_tbls *dev_tbls;
368 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
369 if (!dev_tbls->result_field_list) {
375 idx = tbl->result_start_idx;
376 *num_flds = tbl->result_num_fields;
377 *num_encap_flds = tbl->encap_num_fields;
379 return &dev_tbls->result_field_list[idx];
383 * Get the list of ident fields that implement the flow
385 * tbl [in] A single table instance to get the ident fields from
387 * num_flds [out] The number of ident fields in the returned array
389 * returns array of ident fields, or NULL on error
391 static struct bnxt_ulp_mapper_ident_info *
392 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_parms *mparms,
393 struct bnxt_ulp_mapper_tbl_info *tbl,
397 const struct bnxt_ulp_template_device_tbls *dev_tbls;
399 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
400 if (!dev_tbls->ident_list) {
405 idx = tbl->ident_start_idx;
406 *num_flds = tbl->ident_nums;
408 return &dev_tbls->ident_list[idx];
411 static inline int32_t
412 ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp __rte_unused,
414 struct ulp_flow_db_res_params *res)
416 struct tf_free_tcam_entry_parms fparms = {
417 .dir = res->direction,
418 .tcam_tbl_type = res->resource_type,
419 .idx = (uint16_t)res->resource_hndl
422 return tf_free_tcam_entry(tfp, &fparms);
425 static inline int32_t
426 ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp,
428 struct ulp_flow_db_res_params *res)
430 struct tf_free_tbl_entry_parms fparms = {
431 .dir = res->direction,
432 .type = res->resource_type,
433 .idx = (uint32_t)res->resource_hndl
437 * Just get the table scope, it will be ignored if not necessary
438 * by the tf_free_tbl_entry
440 (void)bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
442 return tf_free_tbl_entry(tfp, &fparms);
445 static inline int32_t
446 ulp_mapper_em_entry_free(struct bnxt_ulp_context *ulp,
448 struct ulp_flow_db_res_params *res)
450 struct tf_delete_em_entry_parms fparms = { 0 };
453 fparms.dir = res->direction;
454 fparms.flow_handle = res->resource_hndl;
456 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
458 BNXT_TF_DBG(ERR, "Failed to get table scope\n");
462 return tf_delete_em_entry(tfp, &fparms);
465 static inline int32_t
466 ulp_mapper_ident_free(struct bnxt_ulp_context *ulp __rte_unused,
468 struct ulp_flow_db_res_params *res)
470 struct tf_free_identifier_parms fparms = {
471 .dir = res->direction,
472 .ident_type = res->resource_type,
473 .id = (uint16_t)res->resource_hndl
476 return tf_free_identifier(tfp, &fparms);
479 static inline int32_t
480 ulp_mapper_mark_free(struct bnxt_ulp_context *ulp,
481 struct ulp_flow_db_res_params *res)
483 return ulp_mark_db_mark_del(ulp,
488 static inline int32_t
489 ulp_mapper_parent_flow_free(struct bnxt_ulp_context *ulp,
491 struct ulp_flow_db_res_params *res)
493 uint32_t idx, child_fid = 0, parent_idx;
494 struct bnxt_ulp_flow_db *flow_db;
496 parent_idx = (uint32_t)res->resource_hndl;
498 /* check the validity of the parent fid */
499 if (ulp_flow_db_parent_flow_idx_get(ulp, parent_fid, &idx) ||
501 BNXT_TF_DBG(ERR, "invalid parent flow id %x\n", parent_fid);
505 /* Clear all the child flows parent index */
506 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp);
507 while (!ulp_flow_db_parent_child_flow_next_entry_get(flow_db, idx,
509 /* update the child flows resource handle */
510 if (ulp_flow_db_child_flow_reset(ulp, BNXT_ULP_FDB_TYPE_REGULAR,
512 BNXT_TF_DBG(ERR, "failed to reset child flow %x\n",
518 /* free the parent entry in the parent table flow */
519 if (ulp_flow_db_parent_flow_free(ulp, parent_fid)) {
520 BNXT_TF_DBG(ERR, "failed to free parent flow %x\n", parent_fid);
526 static inline int32_t
527 ulp_mapper_child_flow_free(struct bnxt_ulp_context *ulp,
529 struct ulp_flow_db_res_params *res)
533 parent_fid = (uint32_t)res->resource_hndl;
535 return 0; /* Already freed - orphan child*/
537 /* reset the child flow bitset*/
538 if (ulp_flow_db_parent_child_flow_set(ulp, parent_fid, child_fid, 0)) {
539 BNXT_TF_DBG(ERR, "error in resetting child flow bitset %x:%x\n",
540 parent_fid, child_fid);
547 * Process the flow database opcode alloc action.
548 * returns 0 on success
551 ulp_mapper_fdb_opc_alloc_rid(struct bnxt_ulp_mapper_parms *parms,
552 struct bnxt_ulp_mapper_tbl_info *tbl)
558 /* allocate a new fid */
559 rc = ulp_flow_db_fid_alloc(parms->ulp_ctx,
560 BNXT_ULP_FDB_TYPE_RID,
564 "Unable to allocate flow table entry\n");
567 /* Store the allocated fid in regfile*/
569 rc = ulp_regfile_write(parms->regfile, tbl->fdb_operand,
570 tfp_cpu_to_be_64(val64));
572 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
574 ulp_flow_db_fid_free(parms->ulp_ctx,
575 BNXT_ULP_FDB_TYPE_RID, rid);
582 * Process the flow database opcode action.
583 * returns 0 on success.
586 ulp_mapper_fdb_opc_process(struct bnxt_ulp_mapper_parms *parms,
587 struct bnxt_ulp_mapper_tbl_info *tbl,
588 struct ulp_flow_db_res_params *fid_parms)
592 enum bnxt_ulp_fdb_type flow_type;
595 switch (tbl->fdb_opcode) {
596 case BNXT_ULP_FDB_OPC_PUSH_FID:
597 push_fid = parms->fid;
598 flow_type = parms->flow_type;
600 case BNXT_ULP_FDB_OPC_PUSH_RID_REGFILE:
601 /* get the fid from the regfile */
602 rc = ulp_regfile_read(parms->regfile, tbl->fdb_operand,
605 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
609 /* Use the extracted fid to update the flow resource */
610 push_fid = (uint32_t)tfp_be_to_cpu_64(val64);
611 flow_type = BNXT_ULP_FDB_TYPE_RID;
614 return rc; /* Nothing to be done */
617 /* Add the resource to the flow database */
618 rc = ulp_flow_db_resource_add(parms->ulp_ctx, flow_type,
619 push_fid, fid_parms);
621 BNXT_TF_DBG(ERR, "Failed to add res to flow %x rc = %d\n",
627 * Process the flow database opcode action.
628 * returns 0 on success.
631 ulp_mapper_priority_opc_process(struct bnxt_ulp_mapper_parms *parms,
632 struct bnxt_ulp_mapper_tbl_info *tbl,
637 switch (tbl->pri_opcode) {
638 case BNXT_ULP_PRI_OPC_NOT_USED:
641 case BNXT_ULP_PRI_OPC_CONST:
642 *priority = tbl->pri_operand;
644 case BNXT_ULP_PRI_OPC_APP_PRI:
645 *priority = parms->app_priority;
648 BNXT_TF_DBG(ERR, "Priority opcode not supported %d\n",
657 * Process the identifier list in the given table.
658 * Extract the ident from the table entry and
659 * write it to the reg file.
660 * returns 0 on success.
663 ulp_mapper_tbl_ident_scan_ext(struct bnxt_ulp_mapper_parms *parms,
664 struct bnxt_ulp_mapper_tbl_info *tbl,
666 uint32_t byte_data_size,
667 enum bnxt_ulp_byte_order byte_order)
669 struct bnxt_ulp_mapper_ident_info *idents;
670 uint32_t i, num_idents = 0;
673 /* validate the null arguments */
675 BNXT_TF_DBG(ERR, "invalid argument\n");
679 /* Get the ident list and process each one */
680 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
682 for (i = 0; i < num_idents; i++) {
683 /* check the size of the buffer for validation */
684 if ((idents[i].ident_bit_pos + idents[i].ident_bit_size) >
685 ULP_BYTE_2_BITS(byte_data_size) ||
686 idents[i].ident_bit_size > ULP_BYTE_2_BITS(sizeof(val64))) {
687 BNXT_TF_DBG(ERR, "invalid offset or length %x:%x:%x\n",
688 idents[i].ident_bit_pos,
689 idents[i].ident_bit_size,
694 if (byte_order == BNXT_ULP_BYTE_ORDER_LE)
695 ulp_bs_pull_lsb(byte_data, (uint8_t *)&val64,
697 idents[i].ident_bit_pos,
698 idents[i].ident_bit_size);
700 ulp_bs_pull_msb(byte_data, (uint8_t *)&val64,
701 idents[i].ident_bit_pos,
702 idents[i].ident_bit_size);
704 /* Write it to the regfile, val64 is already in big-endian*/
705 if (ulp_regfile_write(parms->regfile,
706 idents[i].regfile_idx, val64)) {
707 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
708 idents[i].regfile_idx);
716 * Process the identifier instruction and either store it in the flow database
717 * or return it in the val (if not NULL) on success. If val is NULL, the
718 * identifier is to be stored in the flow database.
721 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms,
722 struct bnxt_ulp_mapper_tbl_info *tbl,
723 struct bnxt_ulp_mapper_ident_info *ident,
726 struct ulp_flow_db_res_params fid_parms;
729 struct tf_alloc_identifier_parms iparms = { 0 };
730 struct tf_free_identifier_parms free_parms = { 0 };
734 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
736 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
740 idx = ident->regfile_idx;
742 iparms.ident_type = ident->ident_type;
743 iparms.dir = tbl->direction;
745 rc = tf_alloc_identifier(tfp, &iparms);
747 BNXT_TF_DBG(ERR, "Alloc ident %s:%s failed.\n",
748 tf_dir_2_str(iparms.dir),
749 tf_ident_2_str(iparms.ident_type));
753 id = (uint64_t)tfp_cpu_to_be_64(iparms.id);
754 if (ulp_regfile_write(parms->regfile, idx, id)) {
755 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
757 /* Need to free the identifier, so goto error */
761 /* Link the resource to the flow in the flow db */
763 memset(&fid_parms, 0, sizeof(fid_parms));
764 fid_parms.direction = tbl->direction;
765 fid_parms.resource_func = ident->resource_func;
766 fid_parms.resource_type = ident->ident_type;
767 fid_parms.resource_hndl = iparms.id;
768 fid_parms.critical_resource = tbl->critical_resource;
770 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
772 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
774 /* Need to free the identifier, so goto error */
783 /* Need to free the identifier */
784 free_parms.dir = tbl->direction;
785 free_parms.ident_type = ident->ident_type;
786 free_parms.id = iparms.id;
788 (void)tf_free_identifier(tfp, &free_parms);
790 BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n",
792 tf_dir_2_str(tbl->direction));
797 * Process the identifier instruction and extract it from result blob.
798 * Increment the identifier reference count and store it in the flow database.
801 ulp_mapper_ident_extract(struct bnxt_ulp_mapper_parms *parms,
802 struct bnxt_ulp_mapper_tbl_info *tbl,
803 struct bnxt_ulp_mapper_ident_info *ident,
804 struct ulp_blob *res_blob)
806 struct ulp_flow_db_res_params fid_parms;
809 struct tf_search_identifier_parms sparms = { 0 };
810 struct tf_free_identifier_parms free_parms = { 0 };
814 /* Get the tfp from ulp context */
815 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
817 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
821 /* Extract the index from the result blob */
822 rc = ulp_blob_pull(res_blob, (uint8_t *)&idx, sizeof(idx),
823 ident->ident_bit_pos, ident->ident_bit_size);
825 BNXT_TF_DBG(ERR, "Failed to extract identifier from blob\n");
829 /* populate the search params and search identifier shadow table */
830 sparms.ident_type = ident->ident_type;
831 sparms.dir = tbl->direction;
832 /* convert the idx into cpu format */
833 sparms.search_id = tfp_be_to_cpu_32(idx);
835 /* Search identifier also increase the reference count */
836 rc = tf_search_identifier(tfp, &sparms);
838 BNXT_TF_DBG(ERR, "Search ident %s:%s:%x failed.\n",
839 tf_dir_2_str(sparms.dir),
840 tf_ident_2_str(sparms.ident_type),
845 /* Write it to the regfile */
846 id = (uint64_t)tfp_cpu_to_be_64(sparms.search_id);
847 if (ulp_regfile_write(parms->regfile, ident->regfile_idx, id)) {
848 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
850 /* Need to free the identifier, so goto error */
854 /* Link the resource to the flow in the flow db */
855 memset(&fid_parms, 0, sizeof(fid_parms));
856 fid_parms.direction = tbl->direction;
857 fid_parms.resource_func = ident->resource_func;
858 fid_parms.resource_type = ident->ident_type;
859 fid_parms.resource_hndl = sparms.search_id;
860 fid_parms.critical_resource = tbl->critical_resource;
861 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
863 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
865 /* Need to free the identifier, so goto error */
872 /* Need to free the identifier */
873 free_parms.dir = tbl->direction;
874 free_parms.ident_type = ident->ident_type;
875 free_parms.id = sparms.search_id;
876 (void)tf_free_identifier(tfp, &free_parms);
877 BNXT_TF_DBG(ERR, "Ident extract failed for %s:%s:%x\n",
879 tf_dir_2_str(tbl->direction), sparms.search_id);
884 ulp_mapper_field_port_db_process(struct bnxt_ulp_mapper_parms *parms,
885 struct bnxt_ulp_mapper_field_info *fld,
890 enum bnxt_ulp_port_table port_data = val16;
893 case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_MAC:
894 if (ulp_port_db_parent_mac_addr_get(parms->ulp_ctx, port_id,
896 BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
901 BNXT_TF_DBG(ERR, "Invalid port_data %s\n", fld->description);
908 ulp_mapper_field_process_inc_dec(struct bnxt_ulp_mapper_field_info *fld,
909 struct ulp_blob *blob,
911 uint16_t const_val16,
913 uint32_t *update_flag)
915 uint64_t l_val64 = *val64;
917 if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_PLUS_CONST ||
918 fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_PLUS_CONST_POST) {
919 l_val64 += const_val16;
920 l_val64 = tfp_be_to_cpu_64(l_val64);
921 ulp_blob_push_64(blob, &l_val64, bitlen);
922 } else if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_MINUS_CONST ||
923 fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_MINUS_CONST_POST) {
924 l_val64 -= const_val16;
925 l_val64 = tfp_be_to_cpu_64(l_val64);
926 ulp_blob_push_64(blob, &l_val64, bitlen);
928 BNXT_TF_DBG(ERR, "Invalid field opcode %u\n", fld->field_opc);
932 if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_MINUS_CONST_POST ||
933 fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_PLUS_CONST_POST) {
941 ulp_mapper_field_process(struct bnxt_ulp_mapper_parms *parms,
943 struct bnxt_ulp_mapper_field_info *fld,
944 struct ulp_blob *blob,
948 uint32_t val_size = 0, field_size = 0;
949 uint64_t hdr_bit, act_bit, regval;
950 uint16_t write_idx = blob->write_idx;
951 uint16_t idx, size_idx, bitlen, offset;
955 uint32_t src1_sel = 0;
956 enum bnxt_ulp_field_src fld_src;
957 uint8_t *fld_src_oper;
958 enum bnxt_ulp_field_cond_src field_cond_src;
959 uint16_t const_val = 0;
960 uint32_t update_flag = 0;
964 /* process the field opcode */
965 if (fld->field_opc != BNXT_ULP_FIELD_OPC_COND_OP) {
966 field_cond_src = BNXT_ULP_FIELD_COND_SRC_TRUE;
967 /* Read the constant from the second operand */
968 memcpy(&const_val, fld->field_opr2, sizeof(uint16_t));
969 const_val = tfp_be_to_cpu_16(const_val);
971 field_cond_src = fld->field_cond_src;
974 bitlen = fld->field_bit_size;
975 /* Evaluate the condition */
976 switch (field_cond_src) {
977 case BNXT_ULP_FIELD_COND_SRC_TRUE:
980 case BNXT_ULP_FIELD_COND_SRC_CF:
981 if (!ulp_operand_read(fld->field_cond_opr,
982 (uint8_t *)&idx, sizeof(uint16_t))) {
983 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
986 idx = tfp_be_to_cpu_16(idx);
987 if (idx >= BNXT_ULP_CF_IDX_LAST) {
988 BNXT_TF_DBG(ERR, "%s invalid index %u\n", name, idx);
991 /* check if the computed field is set */
992 if (ULP_COMP_FLD_IDX_RD(parms, idx))
995 case BNXT_ULP_FIELD_COND_SRC_RF:
996 if (!ulp_operand_read(fld->field_cond_opr,
997 (uint8_t *)&idx, sizeof(uint16_t))) {
998 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1002 idx = tfp_be_to_cpu_16(idx);
1003 /* Uninitialized regfile entries return 0 */
1004 if (!ulp_regfile_read(parms->regfile, idx, ®val)) {
1005 BNXT_TF_DBG(ERR, "%s regfile[%d] read oob\n",
1012 case BNXT_ULP_FIELD_COND_SRC_ACT_BIT:
1013 if (!ulp_operand_read(fld->field_cond_opr,
1014 (uint8_t *)&act_bit, sizeof(uint64_t))) {
1015 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1018 act_bit = tfp_be_to_cpu_64(act_bit);
1019 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit))
1022 case BNXT_ULP_FIELD_COND_SRC_HDR_BIT:
1023 if (!ulp_operand_read(fld->field_cond_opr,
1024 (uint8_t *)&hdr_bit, sizeof(uint64_t))) {
1025 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1028 hdr_bit = tfp_be_to_cpu_64(hdr_bit);
1029 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, hdr_bit))
1032 case BNXT_ULP_FIELD_COND_SRC_FIELD_BIT:
1033 if (!ulp_operand_read(fld->field_cond_opr, (uint8_t *)&idx,
1034 sizeof(uint16_t))) {
1035 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
1038 idx = tfp_be_to_cpu_16(idx);
1039 /* get the index from the global field list */
1040 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1041 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1045 if (bit && (ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit)))
1049 BNXT_TF_DBG(ERR, "%s invalid field opcode 0x%x at %d\n",
1050 name, fld->field_cond_src, write_idx);
1054 /* pick the selected source */
1056 fld_src = fld->field_src1;
1057 fld_src_oper = fld->field_opr1;
1059 fld_src = fld->field_src2;
1060 fld_src_oper = fld->field_opr2;
1063 /* Perform the action */
1065 case BNXT_ULP_FIELD_SRC_ZERO:
1066 if (ulp_blob_pad_push(blob, bitlen) < 0) {
1067 BNXT_TF_DBG(ERR, "%s too large for blob\n", name);
1071 case BNXT_ULP_FIELD_SRC_CONST:
1073 if (!ulp_blob_push(blob, val, bitlen)) {
1074 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1078 case BNXT_ULP_FIELD_SRC_ONES:
1079 val = mapper_fld_ones;
1080 if (!ulp_blob_push(blob, val, bitlen)) {
1081 BNXT_TF_DBG(ERR, "%s too large for blob\n", name);
1085 case BNXT_ULP_FIELD_SRC_CF:
1086 if (!ulp_operand_read(fld_src_oper,
1087 (uint8_t *)&idx, sizeof(uint16_t))) {
1088 BNXT_TF_DBG(ERR, "%s operand read failed.\n",
1092 idx = tfp_be_to_cpu_16(idx);
1093 if (idx >= BNXT_ULP_CF_IDX_LAST) {
1094 BNXT_TF_DBG(ERR, "%s comp field [%d] read oob\n",
1098 if (fld->field_opc == BNXT_ULP_FIELD_OPC_COND_OP) {
1099 val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
1102 BNXT_TF_DBG(ERR, "%s push to blob failed\n",
1106 } else if (fld->field_opc == BNXT_ULP_FIELD_OPC_PORT_TABLE) {
1107 port_id = ULP_COMP_FLD_IDX_RD(parms, idx);
1108 if (ulp_mapper_field_port_db_process(parms, fld,
1111 BNXT_TF_DBG(ERR, "%s field port table failed\n",
1115 if (!ulp_blob_push(blob, val, bitlen)) {
1116 BNXT_TF_DBG(ERR, "%s push to blob failed\n",
1121 src1_val64 = ULP_COMP_FLD_IDX_RD(parms, idx);
1122 if (ulp_mapper_field_process_inc_dec(fld, blob,
1127 BNXT_TF_DBG(ERR, "%s field cond opc failed\n",
1132 BNXT_TF_DBG(ERR, "%s invalid field cond opc\n",
1138 case BNXT_ULP_FIELD_SRC_RF:
1139 if (!ulp_operand_read(fld_src_oper,
1140 (uint8_t *)&idx, sizeof(uint16_t))) {
1141 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1145 idx = tfp_be_to_cpu_16(idx);
1146 /* Uninitialized regfile entries return 0 */
1147 if (!ulp_regfile_read(parms->regfile, idx, ®val)) {
1148 BNXT_TF_DBG(ERR, "%s regfile[%d] read oob\n",
1152 if (fld->field_opc == BNXT_ULP_FIELD_OPC_COND_OP) {
1153 val = ulp_blob_push_64(blob, ®val, bitlen);
1155 BNXT_TF_DBG(ERR, "%s push to blob failed\n",
1160 if (ulp_mapper_field_process_inc_dec(fld, blob,
1165 BNXT_TF_DBG(ERR, "%s field cond opc failed\n",
1170 regval = tfp_cpu_to_be_64(regval);
1171 if (ulp_regfile_write(parms->regfile, idx,
1174 "Write regfile[%d] fail\n",
1181 case BNXT_ULP_FIELD_SRC_ACT_PROP:
1182 if (!ulp_operand_read(fld_src_oper,
1183 (uint8_t *)&idx, sizeof(uint16_t))) {
1184 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1187 idx = tfp_be_to_cpu_16(idx);
1189 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1190 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
1193 val = &parms->act_prop->act_details[idx];
1194 field_size = ulp_mapper_act_prop_size_get(idx);
1195 if (bitlen < ULP_BYTE_2_BITS(field_size)) {
1196 field_size = field_size - ((bitlen + 7) / 8);
1199 if (!ulp_blob_push(blob, val, bitlen)) {
1200 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1204 case BNXT_ULP_FIELD_SRC_ACT_PROP_SZ:
1205 if (!ulp_operand_read(fld_src_oper,
1206 (uint8_t *)&idx, sizeof(uint16_t))) {
1207 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1210 idx = tfp_be_to_cpu_16(idx);
1212 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1213 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
1216 val = &parms->act_prop->act_details[idx];
1218 /* get the size index next */
1219 if (!ulp_operand_read(&fld_src_oper[sizeof(uint16_t)],
1220 (uint8_t *)&size_idx, sizeof(uint16_t))) {
1221 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1224 size_idx = tfp_be_to_cpu_16(size_idx);
1226 if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1227 BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx);
1230 memcpy(&val_size, &parms->act_prop->act_details[size_idx],
1232 val_size = tfp_be_to_cpu_32(val_size);
1233 val_size = ULP_BYTE_2_BITS(val_size);
1234 ulp_blob_push_encap(blob, val, val_size);
1236 case BNXT_ULP_FIELD_SRC_GLB_RF:
1237 if (!ulp_operand_read(fld_src_oper,
1239 sizeof(uint16_t))) {
1240 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
1243 idx = tfp_be_to_cpu_16(idx);
1244 if (ulp_mapper_glb_resource_read(parms->mapper_data,
1247 BNXT_TF_DBG(ERR, "%s global regfile[%d] read failed.\n",
1251 if (fld->field_opc == BNXT_ULP_FIELD_OPC_COND_OP) {
1252 val = ulp_blob_push_64(blob, ®val, bitlen);
1254 BNXT_TF_DBG(ERR, "%s push to blob failed\n",
1259 if (ulp_mapper_field_process_inc_dec(fld, blob,
1264 BNXT_TF_DBG(ERR, "%s field cond opc failed\n",
1269 BNXT_TF_DBG(ERR, "%s invalid field cond opc\n",
1275 case BNXT_ULP_FIELD_SRC_HF:
1276 if (!ulp_operand_read(fld_src_oper, (uint8_t *)&idx,
1277 sizeof(uint16_t))) {
1278 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
1281 idx = tfp_be_to_cpu_16(idx);
1282 /* get the index from the global field list */
1283 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1284 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1289 val = parms->hdr_field[bit].spec;
1291 val = parms->hdr_field[bit].mask;
1294 * Need to account for how much data was pushed to the header
1295 * field vs how much is to be inserted in the key/mask.
1297 field_size = parms->hdr_field[bit].size;
1298 if (bitlen < ULP_BYTE_2_BITS(field_size)) {
1299 field_size = field_size - ((bitlen + 7) / 8);
1303 if (!ulp_blob_push(blob, val, bitlen)) {
1304 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1308 case BNXT_ULP_FIELD_SRC_HDR_BIT:
1309 if (!ulp_operand_read(fld_src_oper,
1310 (uint8_t *)&hdr_bit, sizeof(uint64_t))) {
1311 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1314 hdr_bit = tfp_be_to_cpu_64(hdr_bit);
1315 memset(tmpval, 0, sizeof(tmpval));
1316 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, hdr_bit))
1318 if (bitlen > ULP_BYTE_2_BITS(sizeof(tmpval))) {
1319 BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name);
1322 if (!ulp_blob_push(blob, tmpval, bitlen)) {
1323 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1328 case BNXT_ULP_FIELD_SRC_ACT_BIT:
1329 if (!ulp_operand_read(fld_src_oper,
1330 (uint8_t *)&act_bit, sizeof(uint64_t))) {
1331 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1334 act_bit = tfp_be_to_cpu_64(act_bit);
1335 memset(tmpval, 0, sizeof(tmpval));
1336 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit))
1338 if (bitlen > ULP_BYTE_2_BITS(sizeof(tmpval))) {
1339 BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name);
1342 if (!ulp_blob_push(blob, tmpval, bitlen)) {
1343 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1348 case BNXT_ULP_FIELD_SRC_FIELD_BIT:
1349 if (!ulp_operand_read(fld_src_oper, (uint8_t *)&idx,
1350 sizeof(uint16_t))) {
1351 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
1354 idx = tfp_be_to_cpu_16(idx);
1355 /* get the index from the global field list */
1356 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1357 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1361 memset(tmpval, 0, sizeof(tmpval));
1362 if (ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit))
1364 if (bitlen > ULP_BYTE_2_BITS(sizeof(tmpval))) {
1365 BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name);
1368 if (!ulp_blob_push(blob, tmpval, bitlen)) {
1369 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1374 case BNXT_ULP_FIELD_SRC_SKIP:
1377 case BNXT_ULP_FIELD_SRC_REJECT:
1379 case BNXT_ULP_FIELD_SRC_SUB_HF:
1380 if (!ulp_operand_read(fld_src_oper,
1381 (uint8_t *)&idx, sizeof(uint16_t))) {
1382 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1385 idx = tfp_be_to_cpu_16(idx);
1386 /* get the index from the global field list */
1387 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1388 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1393 /* get the offset next */
1394 if (!ulp_operand_read(&fld_src_oper[sizeof(uint16_t)],
1395 (uint8_t *)&offset, sizeof(uint16_t))) {
1396 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1399 offset = tfp_be_to_cpu_16(offset);
1400 if ((offset + bitlen) >
1401 ULP_BYTE_2_BITS(parms->hdr_field[bit].size) ||
1402 ULP_BITS_IS_BYTE_NOT_ALIGNED(offset)) {
1403 BNXT_TF_DBG(ERR, "Hdr field[%s] oob\n", name);
1406 offset = ULP_BITS_2_BYTE_NR(offset);
1408 /* write the value into blob */
1410 val = &parms->hdr_field[bit].spec[offset];
1412 val = &parms->hdr_field[bit].mask[offset];
1414 if (!ulp_blob_push(blob, val, bitlen)) {
1415 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1420 BNXT_TF_DBG(ERR, "%s invalid field opcode 0x%x at %d\n",
1421 name, fld_src, write_idx);
1428 * Result table process and fill the result blob.
1429 * data [out] - the result blob data
1432 ulp_mapper_tbl_result_build(struct bnxt_ulp_mapper_parms *parms,
1433 struct bnxt_ulp_mapper_tbl_info *tbl,
1434 struct ulp_blob *data,
1437 struct bnxt_ulp_mapper_field_info *dflds;
1438 uint32_t i, num_flds = 0, encap_flds = 0;
1441 /* Get the result field list */
1442 dflds = ulp_mapper_result_fields_get(parms, tbl, &num_flds,
1445 /* validate the result field list counts */
1446 if ((tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1447 (!num_flds && !encap_flds)) || !dflds ||
1448 (tbl->resource_func != BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1449 (!num_flds || encap_flds))) {
1450 BNXT_TF_DBG(ERR, "Failed to get data fields %x:%x\n",
1451 num_flds, encap_flds);
1455 /* process the result fields, loop through them */
1456 for (i = 0; i < (num_flds + encap_flds); i++) {
1457 /* set the swap index if encap swap bit is enabled */
1458 if (parms->device_params->encap_byte_swap && encap_flds &&
1460 ulp_blob_encap_swap_idx_set(data);
1462 /* Process the result fields */
1463 rc = ulp_mapper_field_process(parms, tbl->direction,
1464 &dflds[i], data, 0, name);
1466 BNXT_TF_DBG(ERR, "data field failed\n");
1471 /* if encap bit swap is enabled perform the bit swap */
1472 if (parms->device_params->encap_byte_swap && encap_flds)
1473 ulp_blob_perform_encap_swap(data);
1479 ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms,
1480 struct bnxt_ulp_mapper_tbl_info *tbl,
1483 struct ulp_flow_db_res_params fid_parms;
1484 uint32_t mark, gfid, mark_flag;
1485 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1488 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1489 !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1490 ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1491 BNXT_ULP_ACT_BIT_MARK)))
1492 return rc; /* no need to perform gfid process */
1494 /* Get the mark id details from action property */
1495 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1497 mark = tfp_be_to_cpu_32(mark);
1499 TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid);
1500 mark_flag = BNXT_ULP_MARK_GLOBAL_HW_FID;
1502 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1505 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1508 fid_parms.direction = tbl->direction;
1509 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1510 fid_parms.critical_resource = tbl->critical_resource;
1511 fid_parms.resource_type = mark_flag;
1512 fid_parms.resource_hndl = gfid;
1513 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1515 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1520 ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms,
1521 struct bnxt_ulp_mapper_tbl_info *tbl)
1523 struct ulp_flow_db_res_params fid_parms;
1524 uint32_t act_idx, mark, mark_flag;
1526 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1529 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1530 !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1531 ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1532 BNXT_ULP_ACT_BIT_MARK)))
1533 return rc; /* no need to perform mark action process */
1535 /* Get the mark id details from action property */
1536 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1538 mark = tfp_be_to_cpu_32(mark);
1540 if (!ulp_regfile_read(parms->regfile,
1541 BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1543 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1546 act_idx = tfp_be_to_cpu_64(val64);
1547 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID;
1548 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1551 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1554 fid_parms.direction = tbl->direction;
1555 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1556 fid_parms.critical_resource = tbl->critical_resource;
1557 fid_parms.resource_type = mark_flag;
1558 fid_parms.resource_hndl = act_idx;
1559 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1561 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1566 ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms,
1567 struct bnxt_ulp_mapper_tbl_info *tbl)
1569 struct ulp_flow_db_res_params fid_parms;
1570 uint32_t act_idx, mark, mark_flag;
1572 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1575 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1576 mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION)
1577 return rc; /* no need to perform mark action process */
1579 /* Get the mark id details from the computed field of dev port id */
1580 mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID);
1582 /* Get the main action pointer */
1583 if (!ulp_regfile_read(parms->regfile,
1584 BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1586 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1589 act_idx = tfp_be_to_cpu_64(val64);
1591 /* Set the mark flag to local fid and vfr flag */
1592 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID;
1594 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1597 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1600 fid_parms.direction = tbl->direction;
1601 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1602 fid_parms.critical_resource = tbl->critical_resource;
1603 fid_parms.resource_type = mark_flag;
1604 fid_parms.resource_hndl = act_idx;
1605 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1607 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1611 /* Tcam table scan the identifier list and allocate each identifier */
1613 ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms *parms,
1614 struct bnxt_ulp_mapper_tbl_info *tbl)
1616 struct bnxt_ulp_mapper_ident_info *idents;
1617 uint32_t num_idents;
1620 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1621 for (i = 0; i < num_idents; i++) {
1622 if (ulp_mapper_ident_process(parms, tbl,
1630 * Tcam table scan the identifier list and extract the identifier from
1634 ulp_mapper_tcam_tbl_scan_ident_extract(struct bnxt_ulp_mapper_parms *parms,
1635 struct bnxt_ulp_mapper_tbl_info *tbl,
1636 struct ulp_blob *data)
1638 struct bnxt_ulp_mapper_ident_info *idents;
1639 uint32_t num_idents = 0, i;
1643 * Extract the listed identifiers from the result field,
1644 * no need to allocate them.
1646 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1647 for (i = 0; i < num_idents; i++) {
1648 rc = ulp_mapper_ident_extract(parms, tbl, &idents[i], data);
1650 BNXT_TF_DBG(ERR, "Error in identifier extraction\n");
1657 /* Internal function to write the tcam entry */
1659 ulp_mapper_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms,
1660 struct bnxt_ulp_mapper_tbl_info *tbl,
1661 struct ulp_blob *key,
1662 struct ulp_blob *mask,
1663 struct ulp_blob *data,
1666 struct tf_set_tcam_entry_parms sparms = { 0 };
1671 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1673 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1677 sparms.dir = tbl->direction;
1678 sparms.tcam_tbl_type = tbl->resource_type;
1680 /* Already verified the key/mask lengths */
1681 sparms.key = ulp_blob_data_get(key, &tmplen);
1682 sparms.mask = ulp_blob_data_get(mask, &tmplen);
1683 sparms.key_sz_in_bits = tbl->key_bit_size;
1684 sparms.result = ulp_blob_data_get(data, &tmplen);
1686 if (tbl->result_bit_size != tmplen) {
1687 BNXT_TF_DBG(ERR, "Result len (%d) != Expected (%d)\n",
1688 tmplen, tbl->result_bit_size);
1691 sparms.result_sz_in_bits = tbl->result_bit_size;
1692 if (tf_set_tcam_entry(tfp, &sparms)) {
1693 BNXT_TF_DBG(ERR, "tcam[%s][%s][%x] write failed.\n",
1694 tf_tcam_tbl_2_str(sparms.tcam_tbl_type),
1695 tf_dir_2_str(sparms.dir), sparms.idx);
1700 rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1702 BNXT_TF_DBG(ERR, "failed mark action processing\n");
1709 /* internal function to post process the key/mask blobs for wildcard tcam tbl */
1710 static void ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob *blob)
1712 ulp_blob_perform_64B_word_swap(blob);
1713 ulp_blob_perform_64B_byte_swap(blob);
1717 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1718 struct bnxt_ulp_mapper_tbl_info *tbl)
1720 struct bnxt_ulp_mapper_key_info *kflds;
1721 struct ulp_blob key, mask, data, update_data;
1722 uint32_t i, num_kflds;
1725 struct tf_alloc_tcam_entry_parms aparms = { 0 };
1726 struct tf_search_tcam_entry_parms searchparms = { 0 };
1727 struct ulp_flow_db_res_params fid_parms = { 0 };
1728 struct tf_free_tcam_entry_parms free_parms = { 0 };
1730 uint16_t tmplen = 0;
1733 /* Skip this if table opcode is NOP */
1734 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_NOT_USED ||
1735 tbl->tbl_opcode >= BNXT_ULP_TCAM_TBL_OPC_LAST) {
1736 BNXT_TF_DBG(ERR, "Invalid tcam table opcode %d\n",
1741 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1743 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1747 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
1748 if (!kflds || !num_kflds) {
1749 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1753 if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
1754 parms->device_params->byte_order) ||
1755 !ulp_blob_init(&mask, tbl->blob_key_bit_size,
1756 parms->device_params->byte_order) ||
1757 !ulp_blob_init(&data, tbl->result_bit_size,
1758 parms->device_params->byte_order) ||
1759 !ulp_blob_init(&update_data, tbl->result_bit_size,
1760 parms->device_params->byte_order)) {
1761 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1765 if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM) {
1766 key.byte_order = BNXT_ULP_BYTE_ORDER_BE;
1767 mask.byte_order = BNXT_ULP_BYTE_ORDER_BE;
1770 /* create the key/mask */
1772 * NOTE: The WC table will require some kind of flag to handle the
1773 * mode bits within the key/mask
1775 for (i = 0; i < num_kflds; i++) {
1777 rc = ulp_mapper_field_process(parms, tbl->direction,
1778 &kflds[i].field_info_spec,
1779 &key, 1, "TCAM Key");
1781 BNXT_TF_DBG(ERR, "Key field set failed %s\n",
1782 kflds[i].field_info_spec.description);
1786 /* Setup the mask */
1787 rc = ulp_mapper_field_process(parms, tbl->direction,
1788 &kflds[i].field_info_mask,
1789 &mask, 0, "TCAM Mask");
1791 BNXT_TF_DBG(ERR, "Mask field set failed %s\n",
1792 kflds[i].field_info_mask.description);
1797 /* For wild card tcam perform the post process to swap the blob */
1798 if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM) {
1799 ulp_mapper_wc_tcam_tbl_post_process(&key);
1800 ulp_mapper_wc_tcam_tbl_post_process(&mask);
1803 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
1804 /* allocate the tcam index */
1805 aparms.dir = tbl->direction;
1806 aparms.tcam_tbl_type = tbl->resource_type;
1807 aparms.key = ulp_blob_data_get(&key, &tmplen);
1808 aparms.key_sz_in_bits = tmplen;
1809 if (tbl->blob_key_bit_size != tmplen) {
1810 BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n",
1811 tmplen, tbl->blob_key_bit_size);
1815 aparms.mask = ulp_blob_data_get(&mask, &tmplen);
1816 if (tbl->blob_key_bit_size != tmplen) {
1817 BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n",
1818 tmplen, tbl->blob_key_bit_size);
1822 /* calculate the entry priority */
1823 rc = ulp_mapper_priority_opc_process(parms, tbl,
1826 BNXT_TF_DBG(ERR, "entry priority process failed\n");
1830 rc = tf_alloc_tcam_entry(tfp, &aparms);
1832 BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
1839 * Searching before allocation to see if we already have an
1840 * entry. This allows re-use of a constrained resource.
1842 searchparms.dir = tbl->direction;
1843 searchparms.tcam_tbl_type = tbl->resource_type;
1844 searchparms.key = ulp_blob_data_get(&key, &tmplen);
1845 searchparms.key_sz_in_bits = tbl->key_bit_size;
1846 searchparms.mask = ulp_blob_data_get(&mask, &tmplen);
1847 searchparms.alloc = 1;
1848 searchparms.result = ulp_blob_data_get(&data, &tmplen);
1849 searchparms.result_sz_in_bits = tbl->result_bit_size;
1851 /* calculate the entry priority */
1852 rc = ulp_mapper_priority_opc_process(parms, tbl,
1853 &searchparms.priority);
1855 BNXT_TF_DBG(ERR, "entry priority process failed\n");
1859 rc = tf_search_tcam_entry(tfp, &searchparms);
1861 BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc);
1865 /* Successful search, check the result */
1866 if (searchparms.search_status == REJECT) {
1867 BNXT_TF_DBG(ERR, "tcam alloc rejected\n");
1870 idx = searchparms.idx;
1871 hit = searchparms.hit;
1874 /* Write the tcam index into the regfile*/
1875 if (ulp_regfile_write(parms->regfile, tbl->tbl_operand,
1876 (uint64_t)tfp_cpu_to_be_64(idx))) {
1877 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
1880 /* Need to free the tcam idx, so goto error */
1884 /* if it is miss then it is same as no search before alloc */
1885 if (!hit || tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
1886 /*Scan identifier list, allocate identifier and update regfile*/
1887 rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl);
1888 /* Create the result blob */
1890 rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
1892 /* write the tcam entry */
1894 rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, &key,
1897 /*Scan identifier list, extract identifier and update regfile*/
1898 rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data);
1903 /* Add the tcam index to the flow database */
1904 fid_parms.direction = tbl->direction;
1905 fid_parms.resource_func = tbl->resource_func;
1906 fid_parms.resource_type = tbl->resource_type;
1907 fid_parms.critical_resource = tbl->critical_resource;
1908 fid_parms.resource_hndl = idx;
1909 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1911 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
1913 /* Need to free the identifier, so goto error */
1919 free_parms.dir = tbl->direction;
1920 free_parms.tcam_tbl_type = tbl->resource_type;
1921 free_parms.idx = idx;
1922 trc = tf_free_tcam_entry(tfp, &free_parms);
1924 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
1925 tbl->resource_type, tbl->direction, idx);
1930 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1931 struct bnxt_ulp_mapper_tbl_info *tbl)
1933 struct bnxt_ulp_mapper_key_info *kflds;
1934 struct ulp_blob key, data;
1935 uint32_t i, num_kflds;
1937 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1938 struct ulp_flow_db_res_params fid_parms = { 0 };
1939 struct tf_insert_em_entry_parms iparms = { 0 };
1940 struct tf_delete_em_entry_parms free_parms = { 0 };
1941 enum bnxt_ulp_flow_mem_type mtype;
1945 rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype);
1947 BNXT_TF_DBG(ERR, "Failed to get the mem type for EM\n");
1951 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
1952 if (!kflds || !num_kflds) {
1953 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1957 /* Initialize the key/result blobs */
1958 if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
1959 parms->device_params->byte_order) ||
1960 !ulp_blob_init(&data, tbl->result_bit_size,
1961 parms->device_params->byte_order)) {
1962 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1966 /* create the key */
1967 for (i = 0; i < num_kflds; i++) {
1969 rc = ulp_mapper_field_process(parms, tbl->direction,
1970 &kflds[i].field_info_spec,
1973 BNXT_TF_DBG(ERR, "Key field set failed.\n");
1979 * TBD: Normally should process identifiers in case of using recycle or
1980 * loopback. Not supporting recycle for now.
1983 /* Create the result data blob */
1984 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "EM Result");
1986 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
1989 /* do the transpose for the internal EM keys */
1990 if (tbl->resource_type == TF_MEM_INTERNAL)
1991 ulp_blob_perform_byte_reverse(&key);
1993 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
1994 &iparms.tbl_scope_id);
1996 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
2001 * NOTE: the actual blob size will differ from the size in the tbl
2002 * entry due to the padding.
2004 iparms.dup_check = 0;
2005 iparms.dir = tbl->direction;
2006 iparms.mem = tbl->resource_type;
2007 iparms.key = ulp_blob_data_get(&key, &tmplen);
2008 iparms.key_sz_in_bits = tbl->key_bit_size;
2009 iparms.em_record = ulp_blob_data_get(&data, &tmplen);
2010 iparms.em_record_sz_in_bits = tbl->result_bit_size;
2012 rc = tf_insert_em_entry(tfp, &iparms);
2014 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
2018 /* Mark action process */
2019 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT &&
2020 tbl->resource_type == TF_MEM_EXTERNAL)
2021 rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id);
2022 else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT &&
2023 tbl->resource_type == TF_MEM_INTERNAL)
2024 rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
2026 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
2030 /* Link the EM resource to the flow in the flow db */
2031 memset(&fid_parms, 0, sizeof(fid_parms));
2032 fid_parms.direction = tbl->direction;
2033 fid_parms.resource_func = tbl->resource_func;
2034 fid_parms.resource_type = tbl->resource_type;
2035 fid_parms.critical_resource = tbl->critical_resource;
2036 fid_parms.resource_hndl = iparms.flow_handle;
2038 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2040 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
2042 /* Need to free the identifier, so goto error */
2048 free_parms.dir = iparms.dir;
2049 free_parms.mem = iparms.mem;
2050 free_parms.tbl_scope_id = iparms.tbl_scope_id;
2051 free_parms.flow_handle = iparms.flow_handle;
2053 trc = tf_delete_em_entry(tfp, &free_parms);
2055 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
2061 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2062 struct bnxt_ulp_mapper_tbl_info *tbl)
2064 struct ulp_flow_db_res_params fid_parms;
2065 struct ulp_blob data;
2066 uint64_t regval = 0;
2068 uint32_t index, hit;
2069 int32_t rc = 0, trc = 0;
2070 struct tf_alloc_tbl_entry_parms aparms = { 0 };
2071 struct tf_search_tbl_entry_parms srchparms = { 0 };
2072 struct tf_set_tbl_entry_parms sparms = { 0 };
2073 struct tf_get_tbl_entry_parms gparms = { 0 };
2074 struct tf_free_tbl_entry_parms free_parms = { 0 };
2075 uint32_t tbl_scope_id;
2076 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
2080 bool search = false;
2081 uint64_t act_rec_size;
2083 /* use the max size if encap is enabled */
2084 if (tbl->encap_num_fields)
2085 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
2087 bit_size = tbl->result_bit_size;
2089 /* Initialize the blob data */
2090 if (!ulp_blob_init(&data, bit_size,
2091 parms->device_params->byte_order)) {
2092 BNXT_TF_DBG(ERR, "Failed to initialize index table blob\n");
2096 /* Get the scope id first */
2097 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
2099 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
2103 switch (tbl->tbl_opcode) {
2104 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE:
2107 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE:
2109 * Build the entry, alloc an index, write the table, and store
2110 * the data in the regfile.
2115 case BNXT_ULP_INDEX_TBL_OPC_SRCH_ALLOC_WR_REGFILE:
2116 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2117 /* Not currently supporting with EXT */
2119 "Ext Table Search Opcode not supported.\n");
2123 * Search for the entry in the tf core. If it is hit, save the
2124 * index in the regfile. If it is a miss, Build the entry,
2125 * alloc an index, write the table, and store the data in the
2126 * regfile (same as ALLOC_WR).
2130 case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE:
2132 * get the index to write to from the regfile and then write
2135 if (!ulp_regfile_read(parms->regfile,
2139 "Failed to get tbl idx from regfile[%d].\n",
2143 index = tfp_be_to_cpu_64(regval);
2144 /* For external, we need to reverse shift */
2145 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2146 index = TF_ACT_REC_PTR_2_OFFSET(index);
2150 case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE:
2151 if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) {
2152 BNXT_TF_DBG(ERR, "Template error, wrong fdb opcode\n");
2156 * get the index to write to from the global regfile and then
2159 if (ulp_mapper_glb_resource_read(parms->mapper_data,
2164 "Failed to get tbl idx from Global "
2169 index = tfp_be_to_cpu_64(regval);
2170 /* For external, we need to reverse shift */
2171 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2172 index = TF_ACT_REC_PTR_2_OFFSET(index);
2175 case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE:
2177 * The read is different from the rest and can be handled here
2178 * instead of trying to use common code. Simply read the table
2179 * with the index from the regfile, scan and store the
2180 * identifiers, and return.
2182 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2183 /* Not currently supporting with EXT */
2185 "Ext Table Read Opcode not supported.\n");
2188 if (!ulp_regfile_read(parms->regfile,
2189 tbl->tbl_operand, ®val)) {
2191 "Failed to get tbl idx from regfile[%d]\n",
2195 index = tfp_be_to_cpu_64(regval);
2196 gparms.dir = tbl->direction;
2197 gparms.type = tbl->resource_type;
2198 gparms.data = ulp_blob_data_get(&data, &tmplen);
2199 gparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tbl->result_bit_size);
2201 rc = tf_get_tbl_entry(tfp, &gparms);
2203 BNXT_TF_DBG(ERR, "Failed to read the tbl entry %d:%d\n",
2204 tbl->resource_type, index);
2208 * Scan the fields in the entry and push them into the regfile.
2210 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2212 gparms.data_sz_in_bytes,
2215 BNXT_TF_DBG(ERR, "Failed to read fields on tbl read "
2221 BNXT_TF_DBG(ERR, "Invalid index table opcode %d\n",
2226 if (write || search) {
2227 /* Get the result fields list */
2228 rc = ulp_mapper_tbl_result_build(parms,
2233 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2239 /* Use the result blob to perform a search */
2240 memset(&srchparms, 0, sizeof(srchparms));
2241 srchparms.dir = tbl->direction;
2242 srchparms.type = tbl->resource_type;
2243 srchparms.alloc = 1;
2244 srchparms.result = ulp_blob_data_get(&data, &tmplen);
2245 srchparms.result_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2246 srchparms.tbl_scope_id = tbl_scope_id;
2247 rc = tf_search_tbl_entry(tfp, &srchparms);
2249 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2250 tf_tbl_type_2_str(tbl->resource_type),
2251 tf_dir_2_str(tbl->direction), rc);
2254 if (srchparms.search_status == REJECT) {
2255 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] rejected.\n",
2256 tf_tbl_type_2_str(tbl->resource_type),
2257 tf_dir_2_str(tbl->direction));
2260 index = srchparms.idx;
2261 hit = srchparms.hit;
2269 aparms.dir = tbl->direction;
2270 aparms.type = tbl->resource_type;
2271 aparms.tbl_scope_id = tbl_scope_id;
2273 /* All failures after the alloc succeeds require a free */
2274 rc = tf_alloc_tbl_entry(tfp, &aparms);
2276 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2277 tf_tbl_type_2_str(tbl->resource_type),
2278 tf_dir_2_str(tbl->direction), rc);
2284 if (search || alloc) {
2286 * Store the index in the regfile since we either allocated it
2289 * Calculate the idx for the result record, for external EM the
2290 * offset needs to be shifted accordingly.
2291 * If external non-inline table types are used then need to
2292 * revisit this logic.
2294 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2295 regval = TF_ACT_REC_OFFSET_2_PTR(index);
2299 rc = ulp_regfile_write(parms->regfile,
2301 tfp_cpu_to_be_64(regval));
2303 BNXT_TF_DBG(ERR, "Failed to write regfile[%d] rc=%d\n",
2304 tbl->tbl_operand, rc);
2310 sparms.dir = tbl->direction;
2311 sparms.type = tbl->resource_type;
2312 sparms.data = ulp_blob_data_get(&data, &tmplen);
2313 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2315 sparms.tbl_scope_id = tbl_scope_id;
2316 rc = tf_set_tbl_entry(tfp, &sparms);
2319 "Index table[%s][%s][%x] write failed "
2321 tf_tbl_type_2_str(sparms.type),
2322 tf_dir_2_str(sparms.dir),
2327 /* Calculate action record size */
2328 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2329 act_rec_size = (ULP_BITS_2_BYTE_NR(tmplen) + 15) / 16;
2331 if (ulp_regfile_write(parms->regfile,
2332 BNXT_ULP_RF_IDX_ACTION_REC_SIZE,
2333 tfp_cpu_to_be_64(act_rec_size)))
2335 "Failed write the act rec size\n");
2339 /* Link the resource to the flow in the flow db */
2340 memset(&fid_parms, 0, sizeof(fid_parms));
2341 fid_parms.direction = tbl->direction;
2342 fid_parms.resource_func = tbl->resource_func;
2343 fid_parms.resource_type = tbl->resource_type;
2344 fid_parms.resource_sub_type = tbl->resource_sub_type;
2345 fid_parms.resource_hndl = index;
2346 fid_parms.critical_resource = tbl->critical_resource;
2348 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2350 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
2355 /* Perform the VF rep action */
2356 rc = ulp_mapper_mark_vfr_idx_process(parms, tbl);
2358 BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc);
2364 * Free the allocated resource since we failed to either
2365 * write to the entry or link the flow
2367 free_parms.dir = tbl->direction;
2368 free_parms.type = tbl->resource_type;
2369 free_parms.idx = index;
2370 free_parms.tbl_scope_id = tbl_scope_id;
2372 trc = tf_free_tbl_entry(tfp, &free_parms);
2374 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
2380 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2381 struct bnxt_ulp_mapper_tbl_info *tbl)
2383 struct ulp_blob data, res_blob;
2387 struct tf_set_if_tbl_entry_parms iftbl_params = { 0 };
2388 struct tf_get_if_tbl_entry_parms get_parms = { 0 };
2389 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
2390 enum bnxt_ulp_if_tbl_opc if_opc = tbl->tbl_opcode;
2393 /* Initialize the blob data */
2394 if (!ulp_blob_init(&data, tbl->result_bit_size,
2395 parms->device_params->byte_order)) {
2396 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2400 /* create the result blob */
2401 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "IFtable Result");
2403 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2407 /* Get the index details */
2409 case BNXT_ULP_IF_TBL_OPC_WR_COMP_FIELD:
2410 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2412 case BNXT_ULP_IF_TBL_OPC_WR_REGFILE:
2413 if (!ulp_regfile_read(parms->regfile, tbl->tbl_operand, &idx)) {
2414 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2418 idx = tfp_be_to_cpu_64(idx);
2420 case BNXT_ULP_IF_TBL_OPC_WR_CONST:
2421 idx = tbl->tbl_operand;
2423 case BNXT_ULP_IF_TBL_OPC_RD_COMP_FIELD:
2424 /* Initialize the result blob */
2425 if (!ulp_blob_init(&res_blob, tbl->result_bit_size,
2426 parms->device_params->byte_order)) {
2427 BNXT_TF_DBG(ERR, "Failed initial result blob\n");
2431 /* read the interface table */
2432 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2433 res_size = ULP_BITS_2_BYTE(tbl->result_bit_size);
2434 get_parms.dir = tbl->direction;
2435 get_parms.type = tbl->resource_type;
2436 get_parms.idx = idx;
2437 get_parms.data = ulp_blob_data_get(&res_blob, &tmplen);
2438 get_parms.data_sz_in_bytes = res_size;
2440 rc = tf_get_if_tbl_entry(tfp, &get_parms);
2442 BNXT_TF_DBG(ERR, "Get table[%d][%s][%x] failed rc=%d\n",
2444 tf_dir_2_str(get_parms.dir),
2448 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2451 res_blob.byte_order);
2453 BNXT_TF_DBG(ERR, "Scan and extract failed rc=%d\n", rc);
2455 case BNXT_ULP_IF_TBL_OPC_NOT_USED:
2456 return rc; /* skip it */
2458 BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n");
2462 /* Perform the tf table set by filling the set params */
2463 iftbl_params.dir = tbl->direction;
2464 iftbl_params.type = tbl->resource_type;
2465 iftbl_params.data = ulp_blob_data_get(&data, &tmplen);
2466 iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2467 iftbl_params.idx = idx;
2469 rc = tf_set_if_tbl_entry(tfp, &iftbl_params);
2471 BNXT_TF_DBG(ERR, "Set table[%d][%s][%x] failed rc=%d\n",
2472 iftbl_params.type,/* TBD: add tf_if_tbl_2_str */
2473 tf_dir_2_str(iftbl_params.dir),
2474 iftbl_params.idx, rc);
2479 * TBD: Need to look at the need to store idx in flow db for restore
2480 * the table to its original state on deletion of this entry.
2486 ulp_mapper_gen_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2487 struct bnxt_ulp_mapper_tbl_info *tbl)
2489 struct bnxt_ulp_mapper_key_info *kflds;
2490 struct ulp_flow_db_res_params fid_parms;
2491 struct ulp_mapper_gen_tbl_entry gen_tbl_ent, *g;
2493 struct ulp_blob key, data;
2496 uint32_t i, ckey, num_kflds = 0;
2497 uint32_t gen_tbl_hit = 0, fdb_write = 0;
2501 /* Get the key fields list and build the key. */
2502 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2503 if (!kflds || !num_kflds) {
2504 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2507 if (!ulp_blob_init(&key, tbl->key_bit_size,
2508 parms->device_params->byte_order)) {
2509 BNXT_TF_DBG(ERR, "Failed to alloc blob\n");
2512 for (i = 0; i < num_kflds; i++) {
2514 rc = ulp_mapper_field_process(parms, tbl->direction,
2515 &kflds[i].field_info_spec,
2516 &key, 1, "Gen Tbl Key");
2519 "Failed to create key for Gen tbl rc=%d\n",
2525 /* Calculate the table index for the generic table*/
2526 tbl_idx = ulp_mapper_gen_tbl_idx_calculate(tbl->resource_sub_type,
2529 BNXT_TF_DBG(ERR, "Invalid table index %x:%x\n",
2530 tbl->resource_sub_type, tbl->direction);
2534 /* The_key is a byte array convert it to a search index */
2535 cache_key = ulp_blob_data_get(&key, &tmplen);
2536 memcpy(&ckey, cache_key, sizeof(ckey));
2537 /* Get the generic table entry */
2538 rc = ulp_mapper_gen_tbl_entry_get(parms->ulp_ctx,
2539 tbl_idx, ckey, &gen_tbl_ent);
2542 "Failed to create key for Gen tbl rc=%d\n", rc);
2545 switch (tbl->tbl_opcode) {
2546 case BNXT_ULP_GENERIC_TBL_OPC_READ:
2547 /* check the reference count */
2548 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2550 /* Scan ident list and create the result blob*/
2551 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2557 "Failed to scan ident list\n");
2560 if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) {
2561 /* increment the reference count */
2562 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2570 case BNXT_ULP_GENERIC_TBL_OPC_WRITE:
2571 /* check the reference count */
2572 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2573 /* a hit then error */
2574 BNXT_TF_DBG(ERR, "generic entry already present %x\n",
2576 return -EINVAL; /* success */
2579 /* Initialize the blob data */
2580 if (!ulp_blob_init(&data, tbl->result_bit_size,
2581 gen_tbl_ent.byte_order)) {
2582 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2586 /* Get the result fields list */
2587 rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
2590 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2593 byte_data = ulp_blob_data_get(&data, &tmplen);
2594 rc = ulp_mapper_gen_tbl_entry_data_set(&gen_tbl_ent,
2596 ULP_BITS_2_BYTE(tmplen));
2598 BNXT_TF_DBG(ERR, "Failed to write generic table\n");
2602 /* increment the reference count */
2603 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2605 parms->shared_hndl = (uint64_t)tbl_idx << 32 | ckey;
2608 BNXT_TF_DBG(ERR, "Invalid table opcode %x\n", tbl->tbl_opcode);
2612 /* Set the generic entry hit */
2613 rc = ulp_regfile_write(parms->regfile,
2614 BNXT_ULP_RF_IDX_GENERIC_TBL_HIT,
2615 tfp_cpu_to_be_64(gen_tbl_hit));
2617 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
2618 BNXT_ULP_RF_IDX_GENERIC_TBL_HIT);
2622 /* add the entry to the flow database */
2624 memset(&fid_parms, 0, sizeof(fid_parms));
2625 fid_parms.direction = tbl->direction;
2626 fid_parms.resource_func = tbl->resource_func;
2627 fid_parms.resource_sub_type = tbl->resource_sub_type;
2628 fid_parms.resource_hndl = ckey;
2629 fid_parms.critical_resource = tbl->critical_resource;
2630 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2632 BNXT_TF_DBG(ERR, "Fail to add gen ent flowdb %d\n", rc);
2638 ulp_mapper_ctrl_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2639 struct bnxt_ulp_mapper_tbl_info *tbl)
2643 /* process the fdb opcode for alloc push */
2644 if (tbl->fdb_opcode == BNXT_ULP_FDB_OPC_ALLOC_RID_REGFILE) {
2645 rc = ulp_mapper_fdb_opc_alloc_rid(parms, tbl);
2647 BNXT_TF_DBG(ERR, "Failed to do fdb alloc\n");
2655 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx,
2656 struct bnxt_ulp_mapper_data *mapper_data)
2658 struct bnxt_ulp_glb_resource_info *glb_res;
2659 uint32_t num_glb_res_ids, idx;
2662 glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids);
2663 if (!glb_res || !num_glb_res_ids) {
2664 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
2668 /* Iterate the global resources and process each one */
2669 for (idx = 0; idx < num_glb_res_ids; idx++) {
2670 switch (glb_res[idx].resource_func) {
2671 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
2672 rc = ulp_mapper_resource_ident_allocate(ulp_ctx,
2676 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2677 rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx,
2682 BNXT_TF_DBG(ERR, "Global resource %x not supported\n",
2683 glb_res[idx].resource_func);
2694 * Function to process the memtype opcode of the mapper table.
2695 * returns 1 to skip the table.
2696 * return 0 to continue processing the table.
2701 ulp_mapper_tbl_memtype_opcode_process(struct bnxt_ulp_mapper_parms *parms,
2702 struct bnxt_ulp_mapper_tbl_info *tbl)
2704 enum bnxt_ulp_flow_mem_type mtype = BNXT_ULP_FLOW_MEM_TYPE_INT;
2707 if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) {
2708 BNXT_TF_DBG(ERR, "Failed to get the mem type\n");
2712 switch (tbl->mem_type_opcode) {
2713 case BNXT_ULP_MEM_TYPE_OPC_EXECUTE_IF_INT:
2714 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT)
2717 case BNXT_ULP_MEM_TYPE_OPC_EXECUTE_IF_EXT:
2718 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT)
2721 case BNXT_ULP_MEM_TYPE_OPC_NOP:
2726 "Invalid arg in mapper in memtype opcode\n");
2733 * Common conditional opcode process routine that is used for both the template
2734 * rejection and table conditional execution.
2737 ulp_mapper_cond_opc_process(struct bnxt_ulp_mapper_parms *parms,
2738 enum bnxt_ulp_cond_opc opc,
2747 case BNXT_ULP_COND_OPC_CF_IS_SET:
2748 if (operand < BNXT_ULP_CF_IDX_LAST) {
2749 *res = ULP_COMP_FLD_IDX_RD(parms, operand);
2751 BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
2756 case BNXT_ULP_COND_OPC_CF_NOT_SET:
2757 if (operand < BNXT_ULP_CF_IDX_LAST) {
2758 *res = !ULP_COMP_FLD_IDX_RD(parms, operand);
2760 BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
2765 case BNXT_ULP_COND_OPC_ACT_BIT_IS_SET:
2766 if (operand < BNXT_ULP_ACT_BIT_LAST) {
2767 *res = ULP_BITMAP_ISSET(parms->act_bitmap->bits,
2770 BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
2775 case BNXT_ULP_COND_OPC_ACT_BIT_NOT_SET:
2776 if (operand < BNXT_ULP_ACT_BIT_LAST) {
2777 *res = !ULP_BITMAP_ISSET(parms->act_bitmap->bits,
2780 BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
2785 case BNXT_ULP_COND_OPC_HDR_BIT_IS_SET:
2786 if (operand < BNXT_ULP_HDR_BIT_LAST) {
2787 *res = ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
2790 BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
2795 case BNXT_ULP_COND_OPC_HDR_BIT_NOT_SET:
2796 if (operand < BNXT_ULP_HDR_BIT_LAST) {
2797 *res = !ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
2800 BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
2805 case BNXT_ULP_COND_OPC_FIELD_BIT_IS_SET:
2806 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
2808 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
2812 *res = ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
2814 case BNXT_ULP_COND_OPC_FIELD_BIT_NOT_SET:
2815 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
2817 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
2821 *res = !ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
2823 case BNXT_ULP_COND_OPC_RF_IS_SET:
2824 if (!ulp_regfile_read(parms->regfile, operand, ®val)) {
2825 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
2830 case BNXT_ULP_COND_OPC_RF_NOT_SET:
2831 if (!ulp_regfile_read(parms->regfile, operand, ®val)) {
2832 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
2837 case BNXT_ULP_COND_OPC_FLOW_PAT_MATCH:
2838 if (parms->flow_pattern_id == operand) {
2839 BNXT_TF_DBG(ERR, "field pattern match failed %x\n",
2840 parms->flow_pattern_id);
2844 case BNXT_ULP_COND_OPC_ACT_PAT_MATCH:
2845 if (parms->act_pattern_id == operand) {
2846 BNXT_TF_DBG(ERR, "act pattern match failed %x\n",
2847 parms->act_pattern_id);
2852 BNXT_TF_DBG(ERR, "Invalid conditional opcode %d\n", opc);
2860 * Processes a list of conditions and returns both a status and result of the
2861 * list. The status must be checked prior to verifying the result.
2863 * returns 0 for success, negative on failure
2864 * returns res = 1 for true, res = 0 for false.
2867 ulp_mapper_cond_opc_list_process(struct bnxt_ulp_mapper_parms *parms,
2868 enum bnxt_ulp_cond_list_opc list_opc,
2869 struct bnxt_ulp_mapper_cond_info *list,
2874 int32_t rc = 0, trc = 0;
2877 case BNXT_ULP_COND_LIST_OPC_AND:
2878 /* AND Defaults to true. */
2881 case BNXT_ULP_COND_LIST_OPC_OR:
2882 /* OR Defaults to false. */
2885 case BNXT_ULP_COND_LIST_OPC_TRUE:
2888 case BNXT_ULP_COND_LIST_OPC_FALSE:
2892 BNXT_TF_DBG(ERR, "Invalid conditional list opcode %d\n",
2897 for (i = 0; i < num; i++) {
2898 rc = ulp_mapper_cond_opc_process(parms,
2899 list[i].cond_opcode,
2900 list[i].cond_operand,
2905 if (list_opc == BNXT_ULP_COND_LIST_OPC_AND) {
2906 /* early return if result is ever zero */
2912 /* early return if result is ever non-zero */
2924 * Processes conflict resolution and returns both a status and result.
2925 * The status must be checked prior to verifying the result.
2927 * returns 0 for success, negative on failure
2928 * returns res = 1 for true, res = 0 for false.
2931 ulp_mapper_conflict_resolution_process(struct bnxt_ulp_mapper_parms *parms,
2932 struct bnxt_ulp_mapper_tbl_info *tbl,
2937 uint64_t comp_sig_id;
2940 switch (tbl->accept_opcode) {
2941 case BNXT_ULP_ACCEPT_OPC_ALWAYS:
2944 case BNXT_ULP_ACCEPT_OPC_FLOW_SIG_ID_MATCH:
2945 /* perform the signature validation*/
2946 if (tbl->resource_func ==
2947 BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE) {
2948 /* Perform the check that generic table is hit or not */
2949 if (!ulp_regfile_read(parms->regfile,
2950 BNXT_ULP_RF_IDX_GENERIC_TBL_HIT,
2952 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2953 BNXT_ULP_RF_IDX_GENERIC_TBL_HIT);
2957 /* not a hit so no need to check flow sign*/
2962 /* compare the new flow signature against stored one */
2963 if (!ulp_regfile_read(parms->regfile,
2964 BNXT_ULP_RF_IDX_FLOW_SIG_ID,
2966 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2967 BNXT_ULP_RF_IDX_FLOW_SIG_ID);
2970 comp_sig_id = ULP_COMP_FLD_IDX_RD(parms,
2971 BNXT_ULP_CF_IDX_FLOW_SIG_ID);
2972 regval = tfp_be_to_cpu_64(regval);
2973 if (comp_sig_id == regval)
2976 BNXT_TF_DBG(ERR, "failed signature match %x:%x\n",
2977 (uint32_t)comp_sig_id, (uint32_t)regval);
2980 BNXT_TF_DBG(ERR, "Invalid accept opcode %d\n",
2981 tbl->accept_opcode);
2988 ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid)
2990 struct bnxt_ulp_mapper_cond_info *cond_tbls = NULL;
2991 enum bnxt_ulp_cond_list_opc cond_opc;
2992 struct bnxt_ulp_mapper_tbl_info *tbls;
2993 struct bnxt_ulp_mapper_tbl_info *tbl;
2994 uint32_t num_tbls, tbl_idx, num_cond_tbls;
2995 int32_t rc = -EINVAL, cond_rc = 0;
2996 int32_t cond_goto = 1;
2998 cond_tbls = ulp_mapper_tmpl_reject_list_get(parms, tid,
3002 * Process the reject list if exists, otherwise assume that the
3003 * template is allowed.
3005 if (cond_tbls && num_cond_tbls) {
3006 rc = ulp_mapper_cond_opc_list_process(parms,
3014 /* Reject the template if True */
3016 BNXT_TF_DBG(ERR, "%s Template %d rejected.\n",
3017 ulp_mapper_tmpl_name_str(parms->tmpl_type),
3023 tbls = ulp_mapper_tbl_list_get(parms, tid, &num_tbls);
3024 if (!tbls || !num_tbls) {
3025 BNXT_TF_DBG(ERR, "No %s tables for %d:%d\n",
3026 ulp_mapper_tmpl_name_str(parms->tmpl_type),
3027 parms->dev_id, tid);
3031 for (tbl_idx = 0; tbl_idx < num_tbls && cond_goto;) {
3032 tbl = &tbls[tbl_idx];
3033 /* Handle the table level opcodes to determine if required. */
3034 if (ulp_mapper_tbl_memtype_opcode_process(parms, tbl)) {
3035 cond_goto = tbl->execute_info.cond_false_goto;
3036 goto next_iteration;
3039 cond_tbls = ulp_mapper_tbl_execute_list_get(parms, tbl,
3042 rc = ulp_mapper_cond_opc_list_process(parms, cond_opc,
3043 cond_tbls, num_cond_tbls,
3046 BNXT_TF_DBG(ERR, "Failed to process cond opc list "
3050 /* Skip the table if False */
3052 cond_goto = tbl->execute_info.cond_false_goto;
3053 goto next_iteration;
3056 switch (tbl->resource_func) {
3057 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
3058 rc = ulp_mapper_tcam_tbl_process(parms, tbl);
3060 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
3061 rc = ulp_mapper_em_tbl_process(parms, tbl);
3063 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3064 rc = ulp_mapper_index_tbl_process(parms, tbl);
3066 case BNXT_ULP_RESOURCE_FUNC_IF_TABLE:
3067 rc = ulp_mapper_if_tbl_process(parms, tbl);
3069 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
3070 rc = ulp_mapper_gen_tbl_process(parms, tbl);
3072 case BNXT_ULP_RESOURCE_FUNC_CTRL_TABLE:
3073 rc = ulp_mapper_ctrl_tbl_process(parms, tbl);
3075 case BNXT_ULP_RESOURCE_FUNC_INVALID:
3079 BNXT_TF_DBG(ERR, "Unexpected mapper resource %d\n",
3080 tbl->resource_func);
3086 BNXT_TF_DBG(ERR, "Resource type %d failed\n",
3087 tbl->resource_func);
3091 /* perform the post table process */
3092 rc = ulp_mapper_conflict_resolution_process(parms, tbl,
3094 if (rc || !cond_rc) {
3095 BNXT_TF_DBG(ERR, "Failed due to conflict resolution\n");
3100 if (cond_goto < 0 && ((int32_t)tbl_idx + cond_goto) < 0) {
3101 BNXT_TF_DBG(ERR, "invalid conditional goto %d\n",
3105 tbl_idx += cond_goto;
3110 BNXT_TF_DBG(ERR, "%s tables failed creation for %d:%d\n",
3111 ulp_mapper_tmpl_name_str(parms->tmpl_type),
3112 parms->dev_id, tid);
3117 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
3119 struct ulp_flow_db_res_params *res)
3125 BNXT_TF_DBG(ERR, "Unable to free resource\n ");
3129 tfp = bnxt_ulp_cntxt_tfp_get(ulp);
3131 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
3135 switch (res->resource_func) {
3136 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
3137 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
3139 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
3140 rc = ulp_mapper_em_entry_free(ulp, tfp, res);
3142 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3143 rc = ulp_mapper_index_entry_free(ulp, tfp, res);
3145 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
3146 rc = ulp_mapper_ident_free(ulp, tfp, res);
3148 case BNXT_ULP_RESOURCE_FUNC_HW_FID:
3149 rc = ulp_mapper_mark_free(ulp, res);
3151 case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW:
3152 rc = ulp_mapper_parent_flow_free(ulp, fid, res);
3154 case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW:
3155 rc = ulp_mapper_child_flow_free(ulp, fid, res);
3157 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
3158 rc = ulp_mapper_gen_tbl_res_free(ulp, res);
3168 ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx,
3169 enum bnxt_ulp_fdb_type flow_type,
3172 struct ulp_flow_db_res_params res_parms = { 0 };
3176 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
3181 * Set the critical resource on the first resource del, then iterate
3182 * while status is good
3184 if (flow_type != BNXT_ULP_FDB_TYPE_RID)
3185 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES;
3187 rc = ulp_flow_db_resource_del(ulp_ctx, flow_type, fid, &res_parms);
3191 * This is unexpected on the first call to resource del.
3192 * It likely means that the flow did not exist in the flow db.
3194 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
3195 flow_type, fid, rc);
3200 trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms);
3203 * On fail, we still need to attempt to free the
3204 * remaining resources. Don't return
3207 "Flow[%d][0x%x] Res[%d][0x%016" PRIx64
3208 "] failed rc=%d.\n",
3209 flow_type, fid, res_parms.resource_func,
3210 res_parms.resource_hndl, trc);
3212 /* All subsequent call require the non-critical_resource */
3213 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
3215 rc = ulp_flow_db_resource_del(ulp_ctx,
3221 /* Free the Flow ID since we've removed all resources */
3222 rc = ulp_flow_db_fid_free(ulp_ctx, flow_type, fid);
3228 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx,
3229 struct bnxt_ulp_mapper_data *mapper_data)
3231 struct bnxt_ulp_mapper_glb_resource_entry *ent;
3232 struct ulp_flow_db_res_params res;
3235 /* Iterate the global resources and process each one */
3236 for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) {
3237 for (idx = 0; idx < BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
3239 ent = &mapper_data->glb_res_tbl[dir][idx];
3240 if (ent->resource_func ==
3241 BNXT_ULP_RESOURCE_FUNC_INVALID)
3243 memset(&res, 0, sizeof(struct ulp_flow_db_res_params));
3244 res.resource_func = ent->resource_func;
3245 res.direction = dir;
3246 res.resource_type = ent->resource_type;
3247 /*convert it from BE to cpu */
3249 tfp_be_to_cpu_64(ent->resource_hndl);
3250 ulp_mapper_resource_free(ulp_ctx, 0, &res);
3256 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx,
3257 enum bnxt_ulp_fdb_type flow_type,
3263 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
3267 rc = ulp_mapper_resources_free(ulp_ctx, flow_type, fid);
3271 /* Function to handle the default global templates that are allocated during
3272 * the startup and reused later.
3275 ulp_mapper_glb_template_table_init(struct bnxt_ulp_context *ulp_ctx)
3277 uint32_t *glbl_tmpl_list;
3278 uint32_t num_glb_tmpls, idx, dev_id;
3279 struct bnxt_ulp_mapper_parms parms;
3280 struct bnxt_ulp_mapper_data *mapper_data;
3283 glbl_tmpl_list = ulp_mapper_glb_template_table_get(&num_glb_tmpls);
3284 if (!glbl_tmpl_list || !num_glb_tmpls)
3285 return rc; /* No global templates to process */
3287 /* Get the device id from the ulp context */
3288 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) {
3289 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
3293 mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3295 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
3299 /* Iterate the global resources and process each one */
3300 for (idx = 0; idx < num_glb_tmpls; idx++) {
3301 /* Initialize the parms structure */
3302 memset(&parms, 0, sizeof(parms));
3303 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3304 parms.ulp_ctx = ulp_ctx;
3305 parms.dev_id = dev_id;
3306 parms.mapper_data = mapper_data;
3307 parms.flow_type = BNXT_ULP_FDB_TYPE_DEFAULT;
3308 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
3310 /* Get the class table entry from dev id and class id */
3311 parms.class_tid = glbl_tmpl_list[idx];
3313 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
3314 if (!parms.device_params) {
3315 BNXT_TF_DBG(ERR, "No device for device id %d\n",
3320 rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
3327 /* Function to handle the mapping of the Flow to be compatible
3328 * with the underlying hardware.
3331 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
3332 struct bnxt_ulp_mapper_create_parms *cparms)
3334 struct bnxt_ulp_mapper_parms parms;
3335 struct ulp_regfile regfile;
3336 int32_t rc = 0, trc;
3338 if (!ulp_ctx || !cparms)
3341 /* Initialize the parms structure */
3342 memset(&parms, 0, sizeof(parms));
3343 parms.act_prop = cparms->act_prop;
3344 parms.act_bitmap = cparms->act;
3345 parms.hdr_bitmap = cparms->hdr_bitmap;
3346 parms.regfile = ®file;
3347 parms.hdr_field = cparms->hdr_field;
3348 parms.fld_bitmap = cparms->fld_bitmap;
3349 parms.comp_fld = cparms->comp_fld;
3350 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3351 parms.ulp_ctx = ulp_ctx;
3352 parms.act_tid = cparms->act_tid;
3353 parms.class_tid = cparms->class_tid;
3354 parms.flow_type = cparms->flow_type;
3355 parms.parent_flow = cparms->parent_flow;
3356 parms.parent_fid = cparms->parent_fid;
3357 parms.fid = cparms->flow_id;
3358 parms.tun_idx = cparms->tun_idx;
3359 parms.app_priority = cparms->app_priority;
3360 parms.flow_pattern_id = cparms->flow_pattern_id;
3361 parms.act_pattern_id = cparms->act_pattern_id;
3363 /* Get the device id from the ulp context */
3364 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
3365 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
3369 /* Get the device params, it will be used in later processing */
3370 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
3371 if (!parms.device_params) {
3372 BNXT_TF_DBG(ERR, "No device parms for device id %d\n",
3378 * Get the mapper data for dynamic mapper data such as default
3381 parms.mapper_data = (struct bnxt_ulp_mapper_data *)
3382 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3383 if (!parms.mapper_data) {
3384 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
3388 /* initialize the registry file for further processing */
3389 if (!ulp_regfile_init(parms.regfile)) {
3390 BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
3394 /* Process the action template list from the selected action table*/
3395 if (parms.act_tid) {
3396 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_ACTION;
3397 /* Process the action template tables */
3398 rc = ulp_mapper_tbls_process(&parms, parms.act_tid);
3403 if (parms.class_tid) {
3404 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
3406 /* Process the class template tables.*/
3407 rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
3412 /* setup the parent-child details */
3413 if (parms.parent_flow) {
3414 /* create a parent flow details */
3415 rc = ulp_flow_db_parent_flow_create(&parms);
3418 } else if (parms.parent_fid) {
3419 /* create a child flow details */
3420 rc = ulp_flow_db_child_flow_create(&parms);
3428 /* Free all resources that were allocated during flow creation */
3429 trc = ulp_mapper_flow_destroy(ulp_ctx, parms.flow_type,
3432 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
3438 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx)
3440 struct bnxt_ulp_mapper_data *data;
3447 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3451 data = rte_zmalloc("ulp_mapper_data",
3452 sizeof(struct bnxt_ulp_mapper_data), 0);
3454 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n");
3458 if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) {
3459 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n");
3460 /* Don't call deinit since the prof_func wasn't allocated. */
3465 /* Allocate the global resource ids */
3466 rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data);
3468 BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n");
3472 /* Allocate the generic table list */
3473 rc = ulp_mapper_generic_tbl_list_init(data);
3475 BNXT_TF_DBG(ERR, "Failed to initialize generic tbl list\n");
3479 /* Allocate global template table entries */
3480 rc = ulp_mapper_glb_template_table_init(ulp_ctx);
3482 BNXT_TF_DBG(ERR, "Failed to initialize global templates\n");
3488 /* Ignore the return code in favor of returning the original error. */
3489 ulp_mapper_deinit(ulp_ctx);
3494 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx)
3496 struct bnxt_ulp_mapper_data *data;
3501 "Failed to acquire ulp context, so data may "
3502 "not be released.\n");
3506 data = (struct bnxt_ulp_mapper_data *)
3507 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3509 /* Go ahead and return since there is no allocated data. */
3510 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n");
3514 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3516 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n");
3517 /* Free the mapper data regardless of errors. */
3518 goto free_mapper_data;
3521 /* Free the global resource info table entries */
3522 ulp_mapper_glb_resource_info_deinit(ulp_ctx, data);
3525 /* Free the generic table */
3526 (void)ulp_mapper_generic_tbl_list_deinit(data);
3529 /* Reset the data pointer within the ulp_ctx. */
3530 bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL);