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";
41 static struct bnxt_ulp_glb_resource_info *
42 ulp_mapper_glb_resource_info_list_get(uint32_t *num_entries)
46 *num_entries = BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
47 return ulp_glb_resource_tbl;
51 * Read the global resource from the mapper global resource list
53 * The regval is always returned in big-endian.
55 * returns 0 on success
58 ulp_mapper_glb_resource_read(struct bnxt_ulp_mapper_data *mapper_data,
63 if (!mapper_data || !regval ||
64 dir >= TF_DIR_MAX || idx >= BNXT_ULP_GLB_RF_IDX_LAST)
67 *regval = mapper_data->glb_res_tbl[dir][idx].resource_hndl;
72 * Write a global resource to the mapper global resource list
74 * The regval value must be in big-endian.
76 * return 0 on success.
79 ulp_mapper_glb_resource_write(struct bnxt_ulp_mapper_data *data,
80 struct bnxt_ulp_glb_resource_info *res,
83 struct bnxt_ulp_mapper_glb_resource_entry *ent;
85 /* validate the arguments */
86 if (!data || res->direction >= TF_DIR_MAX ||
87 res->glb_regfile_index >= BNXT_ULP_GLB_RF_IDX_LAST)
90 /* write to the mapper data */
91 ent = &data->glb_res_tbl[res->direction][res->glb_regfile_index];
92 ent->resource_func = res->resource_func;
93 ent->resource_type = res->resource_type;
94 ent->resource_hndl = regval;
99 * Internal function to allocate identity resource and store it in mapper data.
101 * returns 0 on success
104 ulp_mapper_resource_ident_allocate(struct bnxt_ulp_context *ulp_ctx,
105 struct bnxt_ulp_mapper_data *mapper_data,
106 struct bnxt_ulp_glb_resource_info *glb_res)
108 struct tf_alloc_identifier_parms iparms = { 0 };
109 struct tf_free_identifier_parms fparms;
114 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
118 iparms.ident_type = glb_res->resource_type;
119 iparms.dir = glb_res->direction;
121 /* Allocate the Identifier using tf api */
122 rc = tf_alloc_identifier(tfp, &iparms);
124 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
125 tf_dir_2_str(iparms.dir),
130 /* entries are stored as big-endian format */
131 regval = tfp_cpu_to_be_64((uint64_t)iparms.id);
132 /* write to the mapper global resource */
133 rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval);
135 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
136 /* Free the identifier when update failed */
137 fparms.dir = iparms.dir;
138 fparms.ident_type = iparms.ident_type;
139 fparms.id = iparms.id;
140 tf_free_identifier(tfp, &fparms);
147 * Internal function to allocate index tbl resource and store it in mapper data.
149 * returns 0 on success
152 ulp_mapper_resource_index_tbl_alloc(struct bnxt_ulp_context *ulp_ctx,
153 struct bnxt_ulp_mapper_data *mapper_data,
154 struct bnxt_ulp_glb_resource_info *glb_res)
156 struct tf_alloc_tbl_entry_parms aparms = { 0 };
157 struct tf_free_tbl_entry_parms free_parms = { 0 };
160 uint32_t tbl_scope_id;
163 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
167 /* Get the scope id */
168 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &tbl_scope_id);
170 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
174 aparms.type = glb_res->resource_type;
175 aparms.dir = glb_res->direction;
176 aparms.search_enable = 0;
177 aparms.tbl_scope_id = tbl_scope_id;
179 /* Allocate the index tbl using tf api */
180 rc = tf_alloc_tbl_entry(tfp, &aparms);
182 BNXT_TF_DBG(ERR, "Failed to alloc identifier [%s][%d]\n",
183 tf_dir_2_str(aparms.dir), aparms.type);
187 /* entries are stored as big-endian format */
188 regval = tfp_cpu_to_be_64((uint64_t)aparms.idx);
189 /* write to the mapper global resource */
190 rc = ulp_mapper_glb_resource_write(mapper_data, glb_res, regval);
192 BNXT_TF_DBG(ERR, "Failed to write to global resource id\n");
193 /* Free the identifier when update failed */
194 free_parms.dir = aparms.dir;
195 free_parms.type = aparms.type;
196 free_parms.idx = aparms.idx;
197 tf_free_tbl_entry(tfp, &free_parms);
204 ulp_mapper_glb_field_tbl_get(struct bnxt_ulp_mapper_parms *parms,
210 t_idx = parms->class_tid << (BNXT_ULP_HDR_SIG_ID_SHIFT +
211 BNXT_ULP_GLB_FIELD_TBL_SHIFT);
212 t_idx += ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_HDR_SIG_ID) <<
213 BNXT_ULP_GLB_FIELD_TBL_SHIFT;
216 if (t_idx >= BNXT_ULP_GLB_FIELD_TBL_SIZE) {
217 BNXT_TF_DBG(ERR, "Invalid hdr field index %x:%x:%x\n",
218 parms->class_tid, t_idx, operand);
220 return -EINVAL; /* error */
222 *val = ulp_glb_field_tbl[t_idx];
227 * Get the size of the action property for a given index.
229 * idx [in] The index for the action property
231 * returns the size of the action property.
234 ulp_mapper_act_prop_size_get(uint32_t idx)
236 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST)
238 return ulp_act_prop_map_table[idx];
241 static struct bnxt_ulp_mapper_cond_info *
242 ulp_mapper_tmpl_reject_list_get(struct bnxt_ulp_mapper_parms *mparms,
245 enum bnxt_ulp_cond_list_opc *opc)
248 const struct bnxt_ulp_template_device_tbls *dev_tbls;
250 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
251 *num_tbls = dev_tbls->tmpl_list[tid].reject_info.cond_nums;
252 *opc = dev_tbls->tmpl_list[tid].reject_info.cond_list_opcode;
253 idx = dev_tbls->tmpl_list[tid].reject_info.cond_start_idx;
255 return &dev_tbls->cond_list[idx];
258 static struct bnxt_ulp_mapper_cond_info *
259 ulp_mapper_tbl_execute_list_get(struct bnxt_ulp_mapper_parms *mparms,
260 struct bnxt_ulp_mapper_tbl_info *tbl,
262 enum bnxt_ulp_cond_list_opc *opc)
265 const struct bnxt_ulp_template_device_tbls *dev_tbls;
267 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
268 *num_tbls = tbl->execute_info.cond_nums;
269 *opc = tbl->execute_info.cond_list_opcode;
270 idx = tbl->execute_info.cond_start_idx;
272 return &dev_tbls->cond_list[idx];
276 * Get a list of classifier tables that implement the flow
277 * Gets a device dependent list of tables that implement the class template id
279 * mparms [in] The mappers parms with data related to the flow.
281 * tid [in] The template id that matches the flow
283 * num_tbls [out] The number of classifier tables in the returned array
285 * returns An array of classifier tables to implement the flow, or NULL on
288 static struct bnxt_ulp_mapper_tbl_info *
289 ulp_mapper_tbl_list_get(struct bnxt_ulp_mapper_parms *mparms,
294 const struct bnxt_ulp_template_device_tbls *dev_tbls;
296 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
298 idx = dev_tbls->tmpl_list[tid].start_tbl_idx;
299 *num_tbls = dev_tbls->tmpl_list[tid].num_tbls;
301 return &dev_tbls->tbl_list[idx];
305 * Get the list of key fields that implement the flow.
307 * mparms [in] The mapper parms with information about the flow
309 * tbl [in] A single table instance to get the key fields from
311 * num_flds [out] The number of key fields in the returned array
313 * Returns array of Key fields, or NULL on error.
315 static struct bnxt_ulp_mapper_key_info *
316 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_parms *mparms,
317 struct bnxt_ulp_mapper_tbl_info *tbl,
321 const struct bnxt_ulp_template_device_tbls *dev_tbls;
323 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
324 if (!dev_tbls->key_info_list) {
329 idx = tbl->key_start_idx;
330 *num_flds = tbl->key_num_fields;
332 return &dev_tbls->key_info_list[idx];
336 * Get the list of data fields that implement the flow.
338 * mparms [in] The mapper parms with information about the flow
340 * tbl [in] A single table instance to get the data fields from
342 * num_flds [out] The number of data fields in the returned array.
344 * num_encap_flds [out] The number of encap fields in the returned array.
346 * Returns array of data fields, or NULL on error.
348 static struct bnxt_ulp_mapper_field_info *
349 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_parms *mparms,
350 struct bnxt_ulp_mapper_tbl_info *tbl,
352 uint32_t *num_encap_flds)
355 const struct bnxt_ulp_template_device_tbls *dev_tbls;
357 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
358 if (!dev_tbls->result_field_list) {
364 idx = tbl->result_start_idx;
365 *num_flds = tbl->result_num_fields;
366 *num_encap_flds = tbl->encap_num_fields;
368 return &dev_tbls->result_field_list[idx];
372 * Get the list of ident fields that implement the flow
374 * tbl [in] A single table instance to get the ident fields from
376 * num_flds [out] The number of ident fields in the returned array
378 * returns array of ident fields, or NULL on error
380 static struct bnxt_ulp_mapper_ident_info *
381 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_parms *mparms,
382 struct bnxt_ulp_mapper_tbl_info *tbl,
386 const struct bnxt_ulp_template_device_tbls *dev_tbls;
388 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
389 if (!dev_tbls->ident_list) {
394 idx = tbl->ident_start_idx;
395 *num_flds = tbl->ident_nums;
397 return &dev_tbls->ident_list[idx];
400 static inline int32_t
401 ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp __rte_unused,
403 struct ulp_flow_db_res_params *res)
405 struct tf_free_tcam_entry_parms fparms = {
406 .dir = res->direction,
407 .tcam_tbl_type = res->resource_type,
408 .idx = (uint16_t)res->resource_hndl
411 return tf_free_tcam_entry(tfp, &fparms);
414 static inline int32_t
415 ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp,
417 struct ulp_flow_db_res_params *res)
419 struct tf_free_tbl_entry_parms fparms = {
420 .dir = res->direction,
421 .type = res->resource_type,
422 .idx = (uint32_t)res->resource_hndl
426 * Just get the table scope, it will be ignored if not necessary
427 * by the tf_free_tbl_entry
429 (void)bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
431 return tf_free_tbl_entry(tfp, &fparms);
434 static inline int32_t
435 ulp_mapper_em_entry_free(struct bnxt_ulp_context *ulp,
437 struct ulp_flow_db_res_params *res)
439 struct tf_delete_em_entry_parms fparms = { 0 };
442 fparms.dir = res->direction;
443 fparms.flow_handle = res->resource_hndl;
445 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
447 BNXT_TF_DBG(ERR, "Failed to get table scope\n");
451 return tf_delete_em_entry(tfp, &fparms);
454 static inline int32_t
455 ulp_mapper_ident_free(struct bnxt_ulp_context *ulp __rte_unused,
457 struct ulp_flow_db_res_params *res)
459 struct tf_free_identifier_parms fparms = {
460 .dir = res->direction,
461 .ident_type = res->resource_type,
462 .id = (uint16_t)res->resource_hndl
465 return tf_free_identifier(tfp, &fparms);
468 static inline int32_t
469 ulp_mapper_mark_free(struct bnxt_ulp_context *ulp,
470 struct ulp_flow_db_res_params *res)
472 return ulp_mark_db_mark_del(ulp,
477 static inline int32_t
478 ulp_mapper_parent_flow_free(struct bnxt_ulp_context *ulp,
480 struct ulp_flow_db_res_params *res)
482 uint32_t idx, child_fid = 0, parent_idx;
483 struct bnxt_ulp_flow_db *flow_db;
485 parent_idx = (uint32_t)res->resource_hndl;
487 /* check the validity of the parent fid */
488 if (ulp_flow_db_parent_flow_idx_get(ulp, parent_fid, &idx) ||
490 BNXT_TF_DBG(ERR, "invalid parent flow id %x\n", parent_fid);
494 /* Clear all the child flows parent index */
495 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp);
496 while (!ulp_flow_db_parent_child_flow_next_entry_get(flow_db, idx,
498 /* update the child flows resource handle */
499 if (ulp_flow_db_child_flow_reset(ulp, BNXT_ULP_FDB_TYPE_REGULAR,
501 BNXT_TF_DBG(ERR, "failed to reset child flow %x\n",
507 /* free the parent entry in the parent table flow */
508 if (ulp_flow_db_parent_flow_free(ulp, parent_fid)) {
509 BNXT_TF_DBG(ERR, "failed to free parent flow %x\n", parent_fid);
515 static inline int32_t
516 ulp_mapper_child_flow_free(struct bnxt_ulp_context *ulp,
518 struct ulp_flow_db_res_params *res)
522 parent_fid = (uint32_t)res->resource_hndl;
524 return 0; /* Already freed - orphan child*/
526 /* reset the child flow bitset*/
527 if (ulp_flow_db_parent_child_flow_set(ulp, parent_fid, child_fid, 0)) {
528 BNXT_TF_DBG(ERR, "error in resetting child flow bitset %x:%x\n",
529 parent_fid, child_fid);
536 * Process the flow database opcode alloc action.
537 * returns 0 on success
540 ulp_mapper_fdb_opc_alloc_rid(struct bnxt_ulp_mapper_parms *parms,
541 struct bnxt_ulp_mapper_tbl_info *tbl)
547 /* allocate a new fid */
548 rc = ulp_flow_db_fid_alloc(parms->ulp_ctx,
549 BNXT_ULP_FDB_TYPE_RID,
553 "Unable to allocate flow table entry\n");
556 /* Store the allocated fid in regfile*/
558 rc = ulp_regfile_write(parms->regfile, tbl->fdb_operand,
559 tfp_cpu_to_be_64(val64));
561 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
563 ulp_flow_db_fid_free(parms->ulp_ctx,
564 BNXT_ULP_FDB_TYPE_RID, rid);
571 * Process the flow database opcode action.
572 * returns 0 on success.
575 ulp_mapper_fdb_opc_process(struct bnxt_ulp_mapper_parms *parms,
576 struct bnxt_ulp_mapper_tbl_info *tbl,
577 struct ulp_flow_db_res_params *fid_parms)
581 enum bnxt_ulp_fdb_type flow_type;
584 switch (tbl->fdb_opcode) {
585 case BNXT_ULP_FDB_OPC_PUSH_FID:
586 push_fid = parms->fid;
587 flow_type = parms->flow_type;
589 case BNXT_ULP_FDB_OPC_PUSH_RID_REGFILE:
590 /* get the fid from the regfile */
591 rc = ulp_regfile_read(parms->regfile, tbl->fdb_operand,
594 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
598 /* Use the extracted fid to update the flow resource */
599 push_fid = (uint32_t)tfp_be_to_cpu_64(val64);
600 flow_type = BNXT_ULP_FDB_TYPE_RID;
603 return rc; /* Nothing to be done */
606 /* Add the resource to the flow database */
607 rc = ulp_flow_db_resource_add(parms->ulp_ctx, flow_type,
608 push_fid, fid_parms);
610 BNXT_TF_DBG(ERR, "Failed to add res to flow %x rc = %d\n",
616 * Process the flow database opcode action.
617 * returns 0 on success.
620 ulp_mapper_priority_opc_process(struct bnxt_ulp_mapper_parms *parms,
621 struct bnxt_ulp_mapper_tbl_info *tbl,
626 switch (tbl->pri_opcode) {
627 case BNXT_ULP_PRI_OPC_NOT_USED:
630 case BNXT_ULP_PRI_OPC_CONST:
631 *priority = tbl->pri_operand;
633 case BNXT_ULP_PRI_OPC_APP_PRI:
634 *priority = parms->app_priority;
637 BNXT_TF_DBG(ERR, "Priority opcode not supported %d\n",
646 * Process the identifier list in the given table.
647 * Extract the ident from the table entry and
648 * write it to the reg file.
649 * returns 0 on success.
652 ulp_mapper_tbl_ident_scan_ext(struct bnxt_ulp_mapper_parms *parms,
653 struct bnxt_ulp_mapper_tbl_info *tbl,
655 uint32_t byte_data_size,
656 enum bnxt_ulp_byte_order byte_order)
658 struct bnxt_ulp_mapper_ident_info *idents;
659 uint32_t i, num_idents = 0;
662 /* validate the null arguments */
664 BNXT_TF_DBG(ERR, "invalid argument\n");
668 /* Get the ident list and process each one */
669 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
671 for (i = 0; i < num_idents; i++) {
672 /* check the size of the buffer for validation */
673 if ((idents[i].ident_bit_pos + idents[i].ident_bit_size) >
674 ULP_BYTE_2_BITS(byte_data_size) ||
675 idents[i].ident_bit_size > ULP_BYTE_2_BITS(sizeof(val64))) {
676 BNXT_TF_DBG(ERR, "invalid offset or length %x:%x:%x\n",
677 idents[i].ident_bit_pos,
678 idents[i].ident_bit_size,
683 if (byte_order == BNXT_ULP_BYTE_ORDER_LE)
684 ulp_bs_pull_lsb(byte_data, (uint8_t *)&val64,
686 idents[i].ident_bit_pos,
687 idents[i].ident_bit_size);
689 ulp_bs_pull_msb(byte_data, (uint8_t *)&val64,
690 idents[i].ident_bit_pos,
691 idents[i].ident_bit_size);
693 /* Write it to the regfile, val64 is already in big-endian*/
694 if (ulp_regfile_write(parms->regfile,
695 idents[i].regfile_idx, val64)) {
696 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
697 idents[i].regfile_idx);
705 * Process the identifier instruction and either store it in the flow database
706 * or return it in the val (if not NULL) on success. If val is NULL, the
707 * identifier is to be stored in the flow database.
710 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms,
711 struct bnxt_ulp_mapper_tbl_info *tbl,
712 struct bnxt_ulp_mapper_ident_info *ident,
715 struct ulp_flow_db_res_params fid_parms;
718 struct tf_alloc_identifier_parms iparms = { 0 };
719 struct tf_free_identifier_parms free_parms = { 0 };
723 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
725 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
729 idx = ident->regfile_idx;
731 iparms.ident_type = ident->ident_type;
732 iparms.dir = tbl->direction;
734 rc = tf_alloc_identifier(tfp, &iparms);
736 BNXT_TF_DBG(ERR, "Alloc ident %s:%s failed.\n",
737 tf_dir_2_str(iparms.dir),
738 tf_ident_2_str(iparms.ident_type));
742 id = (uint64_t)tfp_cpu_to_be_64(iparms.id);
743 if (ulp_regfile_write(parms->regfile, idx, id)) {
744 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
746 /* Need to free the identifier, so goto error */
750 /* Link the resource to the flow in the flow db */
752 memset(&fid_parms, 0, sizeof(fid_parms));
753 fid_parms.direction = tbl->direction;
754 fid_parms.resource_func = ident->resource_func;
755 fid_parms.resource_type = ident->ident_type;
756 fid_parms.resource_hndl = iparms.id;
757 fid_parms.critical_resource = tbl->critical_resource;
759 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
761 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
763 /* Need to free the identifier, so goto error */
772 /* Need to free the identifier */
773 free_parms.dir = tbl->direction;
774 free_parms.ident_type = ident->ident_type;
775 free_parms.id = iparms.id;
777 (void)tf_free_identifier(tfp, &free_parms);
779 BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n",
781 tf_dir_2_str(tbl->direction));
786 * Process the identifier instruction and extract it from result blob.
787 * Increment the identifier reference count and store it in the flow database.
790 ulp_mapper_ident_extract(struct bnxt_ulp_mapper_parms *parms,
791 struct bnxt_ulp_mapper_tbl_info *tbl,
792 struct bnxt_ulp_mapper_ident_info *ident,
793 struct ulp_blob *res_blob)
795 struct ulp_flow_db_res_params fid_parms;
798 struct tf_search_identifier_parms sparms = { 0 };
799 struct tf_free_identifier_parms free_parms = { 0 };
803 /* Get the tfp from ulp context */
804 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
806 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
810 /* Extract the index from the result blob */
811 rc = ulp_blob_pull(res_blob, (uint8_t *)&idx, sizeof(idx),
812 ident->ident_bit_pos, ident->ident_bit_size);
814 BNXT_TF_DBG(ERR, "Failed to extract identifier from blob\n");
818 /* populate the search params and search identifier shadow table */
819 sparms.ident_type = ident->ident_type;
820 sparms.dir = tbl->direction;
821 /* convert the idx into cpu format */
822 sparms.search_id = tfp_be_to_cpu_32(idx);
824 /* Search identifier also increase the reference count */
825 rc = tf_search_identifier(tfp, &sparms);
827 BNXT_TF_DBG(ERR, "Search ident %s:%s:%x failed.\n",
828 tf_dir_2_str(sparms.dir),
829 tf_ident_2_str(sparms.ident_type),
834 /* Write it to the regfile */
835 id = (uint64_t)tfp_cpu_to_be_64(sparms.search_id);
836 if (ulp_regfile_write(parms->regfile, ident->regfile_idx, id)) {
837 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
839 /* Need to free the identifier, so goto error */
843 /* Link the resource to the flow in the flow db */
844 memset(&fid_parms, 0, sizeof(fid_parms));
845 fid_parms.direction = tbl->direction;
846 fid_parms.resource_func = ident->resource_func;
847 fid_parms.resource_type = ident->ident_type;
848 fid_parms.resource_hndl = sparms.search_id;
849 fid_parms.critical_resource = tbl->critical_resource;
850 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
852 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
854 /* Need to free the identifier, so goto error */
861 /* Need to free the identifier */
862 free_parms.dir = tbl->direction;
863 free_parms.ident_type = ident->ident_type;
864 free_parms.id = sparms.search_id;
865 (void)tf_free_identifier(tfp, &free_parms);
866 BNXT_TF_DBG(ERR, "Ident extract failed for %s:%s:%x\n",
868 tf_dir_2_str(tbl->direction), sparms.search_id);
873 ulp_mapper_field_port_db_process(struct bnxt_ulp_mapper_parms *parms,
874 struct bnxt_ulp_mapper_field_info *fld,
879 enum bnxt_ulp_port_table port_data = val16;
882 case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_MAC:
883 if (ulp_port_db_parent_mac_addr_get(parms->ulp_ctx, port_id,
885 BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
889 case BNXT_ULP_PORT_TABLE_DRV_FUNC_MAC:
890 if (ulp_port_db_drv_mac_addr_get(parms->ulp_ctx, port_id,
892 BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
896 case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_VNIC:
897 if (ulp_port_db_parent_vnic_get(parms->ulp_ctx, port_id,
899 BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
904 BNXT_TF_DBG(ERR, "Invalid port_data %s\n", fld->description);
911 ulp_mapper_field_process_inc_dec(struct bnxt_ulp_mapper_field_info *fld,
912 struct ulp_blob *blob,
914 uint16_t const_val16,
916 uint32_t *update_flag)
918 uint64_t l_val64 = *val64;
920 if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_PLUS_CONST ||
921 fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_PLUS_CONST_POST) {
922 l_val64 += const_val16;
923 l_val64 = tfp_be_to_cpu_64(l_val64);
924 ulp_blob_push_64(blob, &l_val64, bitlen);
925 } else if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_MINUS_CONST ||
926 fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_MINUS_CONST_POST) {
927 l_val64 -= const_val16;
928 l_val64 = tfp_be_to_cpu_64(l_val64);
929 ulp_blob_push_64(blob, &l_val64, bitlen);
931 BNXT_TF_DBG(ERR, "Invalid field opcode %u\n", fld->field_opc);
935 if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_MINUS_CONST_POST ||
936 fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_PLUS_CONST_POST) {
944 ulp_mapper_field_process(struct bnxt_ulp_mapper_parms *parms,
946 struct bnxt_ulp_mapper_field_info *fld,
947 struct ulp_blob *blob,
951 uint32_t val_size = 0, field_size = 0;
952 uint64_t hdr_bit, act_bit, regval;
953 uint16_t write_idx = blob->write_idx;
954 uint16_t idx, size_idx, bitlen, offset;
958 uint32_t src1_sel = 0;
959 enum bnxt_ulp_field_src fld_src;
960 uint8_t *fld_src_oper;
961 enum bnxt_ulp_field_cond_src field_cond_src;
962 uint16_t const_val = 0;
963 uint32_t update_flag = 0;
967 /* process the field opcode */
968 if (fld->field_opc != BNXT_ULP_FIELD_OPC_COND_OP) {
969 field_cond_src = BNXT_ULP_FIELD_COND_SRC_TRUE;
970 /* Read the constant from the second operand */
971 memcpy(&const_val, fld->field_opr2, sizeof(uint16_t));
972 const_val = tfp_be_to_cpu_16(const_val);
974 field_cond_src = fld->field_cond_src;
977 bitlen = fld->field_bit_size;
978 /* Evaluate the condition */
979 switch (field_cond_src) {
980 case BNXT_ULP_FIELD_COND_SRC_TRUE:
983 case BNXT_ULP_FIELD_COND_SRC_CF:
984 if (!ulp_operand_read(fld->field_cond_opr,
985 (uint8_t *)&idx, sizeof(uint16_t))) {
986 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
989 idx = tfp_be_to_cpu_16(idx);
990 if (idx >= BNXT_ULP_CF_IDX_LAST) {
991 BNXT_TF_DBG(ERR, "%s invalid index %u\n", name, idx);
994 /* check if the computed field is set */
995 if (ULP_COMP_FLD_IDX_RD(parms, idx))
998 case BNXT_ULP_FIELD_COND_SRC_RF:
999 if (!ulp_operand_read(fld->field_cond_opr,
1000 (uint8_t *)&idx, sizeof(uint16_t))) {
1001 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1005 idx = tfp_be_to_cpu_16(idx);
1006 /* Uninitialized regfile entries return 0 */
1007 if (!ulp_regfile_read(parms->regfile, idx, ®val)) {
1008 BNXT_TF_DBG(ERR, "%s regfile[%d] read oob\n",
1015 case BNXT_ULP_FIELD_COND_SRC_ACT_BIT:
1016 if (!ulp_operand_read(fld->field_cond_opr,
1017 (uint8_t *)&act_bit, sizeof(uint64_t))) {
1018 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1021 act_bit = tfp_be_to_cpu_64(act_bit);
1022 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit))
1025 case BNXT_ULP_FIELD_COND_SRC_HDR_BIT:
1026 if (!ulp_operand_read(fld->field_cond_opr,
1027 (uint8_t *)&hdr_bit, sizeof(uint64_t))) {
1028 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1031 hdr_bit = tfp_be_to_cpu_64(hdr_bit);
1032 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, hdr_bit))
1035 case BNXT_ULP_FIELD_COND_SRC_FIELD_BIT:
1036 if (!ulp_operand_read(fld->field_cond_opr, (uint8_t *)&idx,
1037 sizeof(uint16_t))) {
1038 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
1041 idx = tfp_be_to_cpu_16(idx);
1042 /* get the index from the global field list */
1043 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1044 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1048 if (bit && (ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit)))
1052 BNXT_TF_DBG(ERR, "%s invalid field opcode 0x%x at %d\n",
1053 name, fld->field_cond_src, write_idx);
1057 /* pick the selected source */
1059 fld_src = fld->field_src1;
1060 fld_src_oper = fld->field_opr1;
1062 fld_src = fld->field_src2;
1063 fld_src_oper = fld->field_opr2;
1066 /* Perform the action */
1068 case BNXT_ULP_FIELD_SRC_ZERO:
1069 if (ulp_blob_pad_push(blob, bitlen) < 0) {
1070 BNXT_TF_DBG(ERR, "%s too large for blob\n", name);
1074 case BNXT_ULP_FIELD_SRC_CONST:
1076 if (!ulp_blob_push(blob, val, bitlen)) {
1077 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1081 case BNXT_ULP_FIELD_SRC_ONES:
1082 val = mapper_fld_ones;
1083 if (!ulp_blob_push(blob, val, bitlen)) {
1084 BNXT_TF_DBG(ERR, "%s too large for blob\n", name);
1088 case BNXT_ULP_FIELD_SRC_CF:
1089 if (!ulp_operand_read(fld_src_oper,
1090 (uint8_t *)&idx, sizeof(uint16_t))) {
1091 BNXT_TF_DBG(ERR, "%s operand read failed.\n",
1095 idx = tfp_be_to_cpu_16(idx);
1096 if (idx >= BNXT_ULP_CF_IDX_LAST) {
1097 BNXT_TF_DBG(ERR, "%s comp field [%d] read oob\n",
1101 if (fld->field_opc == BNXT_ULP_FIELD_OPC_COND_OP) {
1102 val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
1105 BNXT_TF_DBG(ERR, "%s push to blob failed\n",
1109 } else if (fld->field_opc == BNXT_ULP_FIELD_OPC_PORT_TABLE) {
1110 port_id = ULP_COMP_FLD_IDX_RD(parms, idx);
1111 if (ulp_mapper_field_port_db_process(parms, fld,
1114 BNXT_TF_DBG(ERR, "%s field port table failed\n",
1118 if (!ulp_blob_push(blob, val, bitlen)) {
1119 BNXT_TF_DBG(ERR, "%s push to blob failed\n",
1124 src1_val64 = ULP_COMP_FLD_IDX_RD(parms, idx);
1125 if (ulp_mapper_field_process_inc_dec(fld, blob,
1130 BNXT_TF_DBG(ERR, "%s field cond opc failed\n",
1135 BNXT_TF_DBG(ERR, "%s invalid field cond opc\n",
1141 case BNXT_ULP_FIELD_SRC_RF:
1142 if (!ulp_operand_read(fld_src_oper,
1143 (uint8_t *)&idx, sizeof(uint16_t))) {
1144 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1148 idx = tfp_be_to_cpu_16(idx);
1149 /* Uninitialized regfile entries return 0 */
1150 if (!ulp_regfile_read(parms->regfile, idx, ®val)) {
1151 BNXT_TF_DBG(ERR, "%s regfile[%d] read oob\n",
1155 if (fld->field_opc == BNXT_ULP_FIELD_OPC_COND_OP) {
1156 val = ulp_blob_push_64(blob, ®val, bitlen);
1158 BNXT_TF_DBG(ERR, "%s push to blob failed\n",
1163 if (ulp_mapper_field_process_inc_dec(fld, blob,
1168 BNXT_TF_DBG(ERR, "%s field cond opc failed\n",
1173 regval = tfp_cpu_to_be_64(regval);
1174 if (ulp_regfile_write(parms->regfile, idx,
1177 "Write regfile[%d] fail\n",
1184 case BNXT_ULP_FIELD_SRC_ACT_PROP:
1185 if (!ulp_operand_read(fld_src_oper,
1186 (uint8_t *)&idx, sizeof(uint16_t))) {
1187 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1190 idx = tfp_be_to_cpu_16(idx);
1192 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1193 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
1196 val = &parms->act_prop->act_details[idx];
1197 field_size = ulp_mapper_act_prop_size_get(idx);
1198 if (bitlen < ULP_BYTE_2_BITS(field_size)) {
1199 field_size = field_size - ((bitlen + 7) / 8);
1202 if (!ulp_blob_push(blob, val, bitlen)) {
1203 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1207 case BNXT_ULP_FIELD_SRC_ACT_PROP_SZ:
1208 if (!ulp_operand_read(fld_src_oper,
1209 (uint8_t *)&idx, sizeof(uint16_t))) {
1210 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1213 idx = tfp_be_to_cpu_16(idx);
1215 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1216 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
1219 val = &parms->act_prop->act_details[idx];
1221 /* get the size index next */
1222 if (!ulp_operand_read(&fld_src_oper[sizeof(uint16_t)],
1223 (uint8_t *)&size_idx, sizeof(uint16_t))) {
1224 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1227 size_idx = tfp_be_to_cpu_16(size_idx);
1229 if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1230 BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx);
1233 memcpy(&val_size, &parms->act_prop->act_details[size_idx],
1235 val_size = tfp_be_to_cpu_32(val_size);
1236 val_size = ULP_BYTE_2_BITS(val_size);
1237 ulp_blob_push_encap(blob, val, val_size);
1239 case BNXT_ULP_FIELD_SRC_GLB_RF:
1240 if (!ulp_operand_read(fld_src_oper,
1242 sizeof(uint16_t))) {
1243 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
1246 idx = tfp_be_to_cpu_16(idx);
1247 if (ulp_mapper_glb_resource_read(parms->mapper_data,
1250 BNXT_TF_DBG(ERR, "%s global regfile[%d] read failed.\n",
1254 if (fld->field_opc == BNXT_ULP_FIELD_OPC_COND_OP) {
1255 val = ulp_blob_push_64(blob, ®val, bitlen);
1257 BNXT_TF_DBG(ERR, "%s push to blob failed\n",
1262 if (ulp_mapper_field_process_inc_dec(fld, blob,
1267 BNXT_TF_DBG(ERR, "%s field cond opc failed\n",
1272 BNXT_TF_DBG(ERR, "%s invalid field cond opc\n",
1278 case BNXT_ULP_FIELD_SRC_HF:
1279 if (!ulp_operand_read(fld_src_oper, (uint8_t *)&idx,
1280 sizeof(uint16_t))) {
1281 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
1284 idx = tfp_be_to_cpu_16(idx);
1285 /* get the index from the global field list */
1286 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1287 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1292 val = parms->hdr_field[bit].spec;
1294 val = parms->hdr_field[bit].mask;
1297 * Need to account for how much data was pushed to the header
1298 * field vs how much is to be inserted in the key/mask.
1300 field_size = parms->hdr_field[bit].size;
1301 if (bitlen < ULP_BYTE_2_BITS(field_size)) {
1302 field_size = field_size - ((bitlen + 7) / 8);
1306 if (!ulp_blob_push(blob, val, bitlen)) {
1307 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1311 case BNXT_ULP_FIELD_SRC_HDR_BIT:
1312 if (!ulp_operand_read(fld_src_oper,
1313 (uint8_t *)&hdr_bit, sizeof(uint64_t))) {
1314 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1317 hdr_bit = tfp_be_to_cpu_64(hdr_bit);
1318 memset(tmpval, 0, sizeof(tmpval));
1319 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, hdr_bit))
1321 if (bitlen > ULP_BYTE_2_BITS(sizeof(tmpval))) {
1322 BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name);
1325 if (!ulp_blob_push(blob, tmpval, bitlen)) {
1326 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1331 case BNXT_ULP_FIELD_SRC_ACT_BIT:
1332 if (!ulp_operand_read(fld_src_oper,
1333 (uint8_t *)&act_bit, sizeof(uint64_t))) {
1334 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1337 act_bit = tfp_be_to_cpu_64(act_bit);
1338 memset(tmpval, 0, sizeof(tmpval));
1339 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit))
1341 if (bitlen > ULP_BYTE_2_BITS(sizeof(tmpval))) {
1342 BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name);
1345 if (!ulp_blob_push(blob, tmpval, bitlen)) {
1346 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1351 case BNXT_ULP_FIELD_SRC_FIELD_BIT:
1352 if (!ulp_operand_read(fld_src_oper, (uint8_t *)&idx,
1353 sizeof(uint16_t))) {
1354 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
1357 idx = tfp_be_to_cpu_16(idx);
1358 /* get the index from the global field list */
1359 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1360 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1364 memset(tmpval, 0, sizeof(tmpval));
1365 if (ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit))
1367 if (bitlen > ULP_BYTE_2_BITS(sizeof(tmpval))) {
1368 BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name);
1371 if (!ulp_blob_push(blob, tmpval, bitlen)) {
1372 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1377 case BNXT_ULP_FIELD_SRC_SKIP:
1380 case BNXT_ULP_FIELD_SRC_REJECT:
1382 case BNXT_ULP_FIELD_SRC_SUB_HF:
1383 if (!ulp_operand_read(fld_src_oper,
1384 (uint8_t *)&idx, sizeof(uint16_t))) {
1385 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1388 idx = tfp_be_to_cpu_16(idx);
1389 /* get the index from the global field list */
1390 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1391 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1396 /* get the offset next */
1397 if (!ulp_operand_read(&fld_src_oper[sizeof(uint16_t)],
1398 (uint8_t *)&offset, sizeof(uint16_t))) {
1399 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1402 offset = tfp_be_to_cpu_16(offset);
1403 if ((offset + bitlen) >
1404 ULP_BYTE_2_BITS(parms->hdr_field[bit].size) ||
1405 ULP_BITS_IS_BYTE_NOT_ALIGNED(offset)) {
1406 BNXT_TF_DBG(ERR, "Hdr field[%s] oob\n", name);
1409 offset = ULP_BITS_2_BYTE_NR(offset);
1411 /* write the value into blob */
1413 val = &parms->hdr_field[bit].spec[offset];
1415 val = &parms->hdr_field[bit].mask[offset];
1417 if (!ulp_blob_push(blob, val, bitlen)) {
1418 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1423 BNXT_TF_DBG(ERR, "%s invalid field opcode 0x%x at %d\n",
1424 name, fld_src, write_idx);
1431 * Result table process and fill the result blob.
1432 * data [out] - the result blob data
1435 ulp_mapper_tbl_result_build(struct bnxt_ulp_mapper_parms *parms,
1436 struct bnxt_ulp_mapper_tbl_info *tbl,
1437 struct ulp_blob *data,
1440 struct bnxt_ulp_mapper_field_info *dflds;
1441 uint32_t i, num_flds = 0, encap_flds = 0;
1444 /* Get the result field list */
1445 dflds = ulp_mapper_result_fields_get(parms, tbl, &num_flds,
1448 /* validate the result field list counts */
1449 if ((tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1450 (!num_flds && !encap_flds)) || !dflds ||
1451 (tbl->resource_func != BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1452 (!num_flds || encap_flds))) {
1453 BNXT_TF_DBG(ERR, "Failed to get data fields %x:%x\n",
1454 num_flds, encap_flds);
1458 /* process the result fields, loop through them */
1459 for (i = 0; i < (num_flds + encap_flds); i++) {
1460 /* set the swap index if encap swap bit is enabled */
1461 if (parms->device_params->encap_byte_swap && encap_flds &&
1463 ulp_blob_encap_swap_idx_set(data);
1465 /* Process the result fields */
1466 rc = ulp_mapper_field_process(parms, tbl->direction,
1467 &dflds[i], data, 0, name);
1469 BNXT_TF_DBG(ERR, "data field failed\n");
1474 /* if encap bit swap is enabled perform the bit swap */
1475 if (parms->device_params->encap_byte_swap && encap_flds)
1476 ulp_blob_perform_encap_swap(data);
1482 ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms,
1483 struct bnxt_ulp_mapper_tbl_info *tbl,
1486 struct ulp_flow_db_res_params fid_parms;
1487 uint32_t mark, gfid, mark_flag;
1488 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1491 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1492 !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1493 ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1494 BNXT_ULP_ACT_BIT_MARK)))
1495 return rc; /* no need to perform gfid process */
1497 /* Get the mark id details from action property */
1498 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1500 mark = tfp_be_to_cpu_32(mark);
1502 TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid);
1503 mark_flag = BNXT_ULP_MARK_GLOBAL_HW_FID;
1505 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1508 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1511 fid_parms.direction = tbl->direction;
1512 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1513 fid_parms.critical_resource = tbl->critical_resource;
1514 fid_parms.resource_type = mark_flag;
1515 fid_parms.resource_hndl = gfid;
1516 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1518 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1523 ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms,
1524 struct bnxt_ulp_mapper_tbl_info *tbl)
1526 struct ulp_flow_db_res_params fid_parms;
1527 uint32_t act_idx, mark, mark_flag;
1529 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1532 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1533 !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1534 ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1535 BNXT_ULP_ACT_BIT_MARK)))
1536 return rc; /* no need to perform mark action process */
1538 /* Get the mark id details from action property */
1539 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1541 mark = tfp_be_to_cpu_32(mark);
1543 if (!ulp_regfile_read(parms->regfile,
1544 BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1546 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1549 act_idx = tfp_be_to_cpu_64(val64);
1550 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID;
1551 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1554 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1557 fid_parms.direction = tbl->direction;
1558 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1559 fid_parms.critical_resource = tbl->critical_resource;
1560 fid_parms.resource_type = mark_flag;
1561 fid_parms.resource_hndl = act_idx;
1562 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1564 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1569 ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms,
1570 struct bnxt_ulp_mapper_tbl_info *tbl)
1572 struct ulp_flow_db_res_params fid_parms;
1573 uint32_t act_idx, mark, mark_flag;
1575 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1578 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1579 mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION)
1580 return rc; /* no need to perform mark action process */
1582 /* Get the mark id details from the computed field of dev port id */
1583 mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID);
1585 /* Get the main action pointer */
1586 if (!ulp_regfile_read(parms->regfile,
1587 BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1589 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1592 act_idx = tfp_be_to_cpu_64(val64);
1594 /* Set the mark flag to local fid and vfr flag */
1595 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID;
1597 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1600 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1603 fid_parms.direction = tbl->direction;
1604 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1605 fid_parms.critical_resource = tbl->critical_resource;
1606 fid_parms.resource_type = mark_flag;
1607 fid_parms.resource_hndl = act_idx;
1608 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1610 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1614 /* Tcam table scan the identifier list and allocate each identifier */
1616 ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms *parms,
1617 struct bnxt_ulp_mapper_tbl_info *tbl)
1619 struct bnxt_ulp_mapper_ident_info *idents;
1620 uint32_t num_idents;
1623 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1624 for (i = 0; i < num_idents; i++) {
1625 if (ulp_mapper_ident_process(parms, tbl,
1633 * Tcam table scan the identifier list and extract the identifier from
1637 ulp_mapper_tcam_tbl_scan_ident_extract(struct bnxt_ulp_mapper_parms *parms,
1638 struct bnxt_ulp_mapper_tbl_info *tbl,
1639 struct ulp_blob *data)
1641 struct bnxt_ulp_mapper_ident_info *idents;
1642 uint32_t num_idents = 0, i;
1646 * Extract the listed identifiers from the result field,
1647 * no need to allocate them.
1649 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1650 for (i = 0; i < num_idents; i++) {
1651 rc = ulp_mapper_ident_extract(parms, tbl, &idents[i], data);
1653 BNXT_TF_DBG(ERR, "Error in identifier extraction\n");
1660 /* Internal function to write the tcam entry */
1662 ulp_mapper_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms,
1663 struct bnxt_ulp_mapper_tbl_info *tbl,
1664 struct ulp_blob *key,
1665 struct ulp_blob *mask,
1666 struct ulp_blob *data,
1669 struct tf_set_tcam_entry_parms sparms = { 0 };
1674 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1676 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1680 sparms.dir = tbl->direction;
1681 sparms.tcam_tbl_type = tbl->resource_type;
1683 sparms.key = ulp_blob_data_get(key, &tmplen);
1684 sparms.key_sz_in_bits = tmplen;
1685 sparms.mask = ulp_blob_data_get(mask, &tmplen);
1686 sparms.result = ulp_blob_data_get(data, &tmplen);
1687 sparms.result_sz_in_bits = tmplen;
1688 if (tf_set_tcam_entry(tfp, &sparms)) {
1689 BNXT_TF_DBG(ERR, "tcam[%s][%s][%x] write failed.\n",
1690 tf_tcam_tbl_2_str(sparms.tcam_tbl_type),
1691 tf_dir_2_str(sparms.dir), sparms.idx);
1696 rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1698 BNXT_TF_DBG(ERR, "failed mark action processing\n");
1706 * internal function to post process key/mask blobs for dynamic pad WC tcam tbl
1708 * parms [in] The mappers parms with data related to the flow.
1710 * key [in] The original key to be transformed
1712 * mask [in] The original mask to be transformed
1714 * tkey [in/out] The transformed key
1716 * tmask [in/out] The transformed mask
1718 * returns zero on success, non-zero on failure
1721 ulp_mapper_wc_tcam_tbl_dyn_post_process(struct bnxt_ulp_device_params *dparms,
1722 struct ulp_blob *key,
1723 struct ulp_blob *mask,
1724 struct ulp_blob *tkey,
1725 struct ulp_blob *tmask)
1727 uint16_t tlen, blen, clen, slice_width, num_slices, max_slices, offset;
1728 uint32_t cword, i, rc;
1732 slice_width = dparms->wc_slice_width;
1733 clen = dparms->wc_ctl_size_bits;
1734 max_slices = dparms->wc_max_slices;
1735 blen = ulp_blob_data_len_get(key);
1737 /* Get the length of the key based on number of slices and width */
1740 while (tlen < blen &&
1741 num_slices <= max_slices) {
1742 num_slices = num_slices << 1;
1746 if (num_slices > max_slices) {
1747 BNXT_TF_DBG(ERR, "Key size (%d) too large for WC\n", blen);
1751 /* The key/mask may not be on a natural slice boundary, pad it */
1753 if (ulp_blob_pad_push(key, pad) < 0 ||
1754 ulp_blob_pad_push(mask, pad) < 0) {
1755 BNXT_TF_DBG(ERR, "Unable to pad key/mask\n");
1759 /* The new length accounts for the ctrl word length and num slices */
1760 tlen = tlen + clen * num_slices;
1761 if (!ulp_blob_init(tkey, tlen, key->byte_order) ||
1762 !ulp_blob_init(tmask, tlen, mask->byte_order)) {
1763 BNXT_TF_DBG(ERR, "Unable to post process wc tcam entry\n");
1767 /* Build the transformed key/mask */
1768 cword = dparms->wc_mode_list[num_slices - 1];
1769 cword = tfp_cpu_to_be_32(cword);
1771 for (i = 0; i < num_slices; i++) {
1772 val = ulp_blob_push_32(tkey, &cword, clen);
1774 BNXT_TF_DBG(ERR, "Key ctrl word push failed\n");
1777 val = ulp_blob_push_32(tmask, &cword, clen);
1779 BNXT_TF_DBG(ERR, "Mask ctrl word push failed\n");
1782 rc = ulp_blob_append(tkey, key, offset, slice_width);
1784 BNXT_TF_DBG(ERR, "Key blob append failed\n");
1787 rc = ulp_blob_append(tmask, mask, offset, slice_width);
1789 BNXT_TF_DBG(ERR, "Mask blob append failed\n");
1792 offset += slice_width;
1795 /* The key/mask are byte reversed on every 4 byte chunk */
1796 ulp_blob_perform_byte_reverse(tkey, 4);
1797 ulp_blob_perform_byte_reverse(tmask, 4);
1802 /* internal function to post process the key/mask blobs for wildcard tcam tbl */
1803 static void ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob *blob)
1805 ulp_blob_perform_64B_word_swap(blob);
1806 ulp_blob_perform_64B_byte_swap(blob);
1810 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1811 struct bnxt_ulp_mapper_tbl_info *tbl)
1813 struct bnxt_ulp_mapper_key_info *kflds;
1814 struct ulp_blob okey, omask, data, update_data;
1815 struct ulp_blob tkey, tmask; /* transform key and mask */
1816 struct ulp_blob *key, *mask;
1817 uint32_t i, num_kflds;
1820 struct bnxt_ulp_device_params *dparms = parms->device_params;
1821 struct tf_alloc_tcam_entry_parms aparms = { 0 };
1822 struct tf_search_tcam_entry_parms searchparms = { 0 };
1823 struct ulp_flow_db_res_params fid_parms = { 0 };
1824 struct tf_free_tcam_entry_parms free_parms = { 0 };
1826 uint16_t tmplen = 0;
1829 /* Set the key and mask to the original key and mask. */
1833 /* Skip this if table opcode is NOP */
1834 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_NOT_USED ||
1835 tbl->tbl_opcode >= BNXT_ULP_TCAM_TBL_OPC_LAST) {
1836 BNXT_TF_DBG(ERR, "Invalid tcam table opcode %d\n",
1841 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1843 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1847 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
1848 if (!kflds || !num_kflds) {
1849 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1853 if (!ulp_blob_init(key, tbl->blob_key_bit_size, tbl->byte_order) ||
1854 !ulp_blob_init(mask, tbl->blob_key_bit_size, tbl->byte_order) ||
1855 !ulp_blob_init(&data, tbl->result_bit_size, dparms->byte_order) ||
1856 !ulp_blob_init(&update_data, tbl->result_bit_size,
1857 dparms->byte_order)) {
1858 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1862 /* create the key/mask */
1864 * NOTE: The WC table will require some kind of flag to handle the
1865 * mode bits within the key/mask
1867 for (i = 0; i < num_kflds; i++) {
1869 rc = ulp_mapper_field_process(parms, tbl->direction,
1870 &kflds[i].field_info_spec,
1871 key, 1, "TCAM Key");
1873 BNXT_TF_DBG(ERR, "Key field set failed %s\n",
1874 kflds[i].field_info_spec.description);
1878 /* Setup the mask */
1879 rc = ulp_mapper_field_process(parms, tbl->direction,
1880 &kflds[i].field_info_mask,
1881 mask, 0, "TCAM Mask");
1883 BNXT_TF_DBG(ERR, "Mask field set failed %s\n",
1884 kflds[i].field_info_mask.description);
1889 /* For wild card tcam perform the post process to swap the blob */
1890 if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM) {
1891 if (dparms->dynamic_pad_en) {
1892 /* Sets up the slices for writing to the WC TCAM */
1893 rc = ulp_mapper_wc_tcam_tbl_dyn_post_process(dparms,
1899 "Failed to post proc WC entry.\n");
1902 /* Now need to use the transform Key/Mask */
1906 ulp_mapper_wc_tcam_tbl_post_process(key);
1907 ulp_mapper_wc_tcam_tbl_post_process(mask);
1912 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
1913 /* allocate the tcam index */
1914 aparms.dir = tbl->direction;
1915 aparms.tcam_tbl_type = tbl->resource_type;
1916 aparms.key = ulp_blob_data_get(key, &tmplen);
1917 aparms.key_sz_in_bits = tmplen;
1918 aparms.mask = ulp_blob_data_get(mask, &tmplen);
1920 /* calculate the entry priority */
1921 rc = ulp_mapper_priority_opc_process(parms, tbl,
1924 BNXT_TF_DBG(ERR, "entry priority process failed\n");
1928 rc = tf_alloc_tcam_entry(tfp, &aparms);
1930 BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
1937 * Searching before allocation to see if we already have an
1938 * entry. This allows re-use of a constrained resource.
1940 searchparms.dir = tbl->direction;
1941 searchparms.tcam_tbl_type = tbl->resource_type;
1942 searchparms.key = ulp_blob_data_get(key, &tmplen);
1943 searchparms.key_sz_in_bits = tbl->key_bit_size;
1944 searchparms.mask = ulp_blob_data_get(mask, &tmplen);
1945 searchparms.alloc = 1;
1946 searchparms.result = ulp_blob_data_get(&data, &tmplen);
1947 searchparms.result_sz_in_bits = tbl->result_bit_size;
1949 /* calculate the entry priority */
1950 rc = ulp_mapper_priority_opc_process(parms, tbl,
1951 &searchparms.priority);
1953 BNXT_TF_DBG(ERR, "entry priority process failed\n");
1957 rc = tf_search_tcam_entry(tfp, &searchparms);
1959 BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc);
1963 /* Successful search, check the result */
1964 if (searchparms.search_status == REJECT) {
1965 BNXT_TF_DBG(ERR, "tcam alloc rejected\n");
1968 idx = searchparms.idx;
1969 hit = searchparms.hit;
1972 /* Write the tcam index into the regfile*/
1973 if (ulp_regfile_write(parms->regfile, tbl->tbl_operand,
1974 (uint64_t)tfp_cpu_to_be_64(idx))) {
1975 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
1978 /* Need to free the tcam idx, so goto error */
1982 /* if it is miss then it is same as no search before alloc */
1983 if (!hit || tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
1984 /*Scan identifier list, allocate identifier and update regfile*/
1985 rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl);
1986 /* Create the result blob */
1988 rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
1990 /* write the tcam entry */
1992 rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, key,
1995 /*Scan identifier list, extract identifier and update regfile*/
1996 rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data);
2001 /* Add the tcam index to the flow database */
2002 fid_parms.direction = tbl->direction;
2003 fid_parms.resource_func = tbl->resource_func;
2004 fid_parms.resource_type = tbl->resource_type;
2005 fid_parms.critical_resource = tbl->critical_resource;
2006 fid_parms.resource_hndl = idx;
2007 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2009 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
2011 /* Need to free the identifier, so goto error */
2017 free_parms.dir = tbl->direction;
2018 free_parms.tcam_tbl_type = tbl->resource_type;
2019 free_parms.idx = idx;
2020 trc = tf_free_tcam_entry(tfp, &free_parms);
2022 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
2023 tbl->resource_type, tbl->direction, idx);
2028 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2029 struct bnxt_ulp_mapper_tbl_info *tbl)
2031 struct bnxt_ulp_mapper_key_info *kflds;
2032 struct ulp_blob key, data;
2033 uint32_t i, num_kflds;
2035 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
2036 struct ulp_flow_db_res_params fid_parms = { 0 };
2037 struct tf_insert_em_entry_parms iparms = { 0 };
2038 struct tf_delete_em_entry_parms free_parms = { 0 };
2039 enum bnxt_ulp_flow_mem_type mtype;
2040 struct bnxt_ulp_device_params *dparms = parms->device_params;
2045 rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype);
2047 BNXT_TF_DBG(ERR, "Failed to get the mem type for EM\n");
2051 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2052 if (!kflds || !num_kflds) {
2053 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2057 /* Initialize the key/result blobs */
2058 if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
2060 !ulp_blob_init(&data, tbl->result_bit_size,
2062 BNXT_TF_DBG(ERR, "blob inits failed.\n");
2066 /* create the key */
2067 for (i = 0; i < num_kflds; i++) {
2069 rc = ulp_mapper_field_process(parms, tbl->direction,
2070 &kflds[i].field_info_spec,
2073 BNXT_TF_DBG(ERR, "Key field set failed.\n");
2078 /* if dynamic padding is enabled then add padding to result data */
2079 if (dparms->dynamic_pad_en) {
2080 /* add padding to make sure key is at byte boundary */
2081 ulp_blob_pad_align(&key, ULP_BUFFER_ALIGN_8_BITS);
2084 pad = dparms->em_blk_align_bits - dparms->em_blk_size_bits;
2086 BNXT_TF_DBG(ERR, "Invalid em blk size and align\n");
2089 ulp_blob_pad_push(&data, (uint32_t)pad);
2092 /* Create the result data blob */
2093 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "EM Result");
2095 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2098 if (dparms->dynamic_pad_en) {
2099 uint32_t abits = dparms->em_blk_align_bits;
2101 /* when dynamic padding is enabled merge result + key */
2102 rc = ulp_blob_block_merge(&data, &key, abits, pad);
2104 BNXT_TF_DBG(ERR, "Failed to merge the result blob\n");
2108 /* add padding to make sure merged result is at slice boundary*/
2109 ulp_blob_pad_align(&data, abits);
2111 ulp_blob_perform_byte_reverse(&data, ULP_BITS_2_BYTE(abits));
2114 /* do the transpose for the internal EM keys */
2115 if (tbl->resource_type == TF_MEM_INTERNAL) {
2116 if (dparms->em_key_align_bytes) {
2117 int32_t b = ULP_BYTE_2_BITS(dparms->em_key_align_bytes);
2119 tmplen = ulp_blob_data_len_get(&key);
2120 ulp_blob_pad_push(&key, b - tmplen);
2122 tmplen = ulp_blob_data_len_get(&key);
2123 ulp_blob_perform_byte_reverse(&key, ULP_BITS_2_BYTE(tmplen));
2126 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
2127 &iparms.tbl_scope_id);
2129 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
2134 * NOTE: the actual blob size will differ from the size in the tbl
2135 * entry due to the padding.
2137 iparms.dup_check = 0;
2138 iparms.dir = tbl->direction;
2139 iparms.mem = tbl->resource_type;
2140 iparms.key = ulp_blob_data_get(&key, &tmplen);
2141 iparms.key_sz_in_bits = tbl->key_bit_size;
2142 iparms.em_record = ulp_blob_data_get(&data, &tmplen);
2143 if (tbl->result_bit_size)
2144 iparms.em_record_sz_in_bits = tbl->result_bit_size;
2146 iparms.em_record_sz_in_bits = tmplen;
2148 rc = tf_insert_em_entry(tfp, &iparms);
2150 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
2154 /* Mark action process */
2155 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT &&
2156 tbl->resource_type == TF_MEM_EXTERNAL)
2157 rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id);
2158 else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT &&
2159 tbl->resource_type == TF_MEM_INTERNAL)
2160 rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
2162 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
2166 /* Link the EM resource to the flow in the flow db */
2167 memset(&fid_parms, 0, sizeof(fid_parms));
2168 fid_parms.direction = tbl->direction;
2169 fid_parms.resource_func = tbl->resource_func;
2170 fid_parms.resource_type = tbl->resource_type;
2171 fid_parms.critical_resource = tbl->critical_resource;
2172 fid_parms.resource_hndl = iparms.flow_handle;
2174 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2176 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
2178 /* Need to free the identifier, so goto error */
2184 free_parms.dir = iparms.dir;
2185 free_parms.mem = iparms.mem;
2186 free_parms.tbl_scope_id = iparms.tbl_scope_id;
2187 free_parms.flow_handle = iparms.flow_handle;
2189 trc = tf_delete_em_entry(tfp, &free_parms);
2191 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
2197 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2198 struct bnxt_ulp_mapper_tbl_info *tbl)
2200 struct ulp_flow_db_res_params fid_parms;
2201 struct ulp_blob data;
2202 uint64_t regval = 0;
2205 int32_t rc = 0, trc = 0;
2206 struct tf_alloc_tbl_entry_parms aparms = { 0 };
2207 struct tf_set_tbl_entry_parms sparms = { 0 };
2208 struct tf_get_tbl_entry_parms gparms = { 0 };
2209 struct tf_free_tbl_entry_parms free_parms = { 0 };
2210 uint32_t tbl_scope_id;
2211 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
2212 struct bnxt_ulp_glb_resource_info glb_res;
2216 bool global = false;
2217 uint64_t act_rec_size;
2219 /* use the max size if encap is enabled */
2220 if (tbl->encap_num_fields)
2221 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
2223 bit_size = tbl->result_bit_size;
2225 /* Initialize the blob data */
2226 if (!ulp_blob_init(&data, bit_size,
2227 parms->device_params->byte_order)) {
2228 BNXT_TF_DBG(ERR, "Failed to initialize index table blob\n");
2232 /* Get the scope id first */
2233 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
2235 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
2239 switch (tbl->tbl_opcode) {
2240 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE:
2243 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE:
2245 * Build the entry, alloc an index, write the table, and store
2246 * the data in the regfile.
2251 case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE:
2253 * get the index to write to from the regfile and then write
2256 if (!ulp_regfile_read(parms->regfile,
2260 "Failed to get tbl idx from regfile[%d].\n",
2264 index = tfp_be_to_cpu_64(regval);
2265 /* For external, we need to reverse shift */
2266 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2267 index = TF_ACT_REC_PTR_2_OFFSET(index);
2271 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_GLB_REGFILE:
2273 * Build the entry, alloc an index, write the table, and store
2274 * the data in the global regfile.
2279 glb_res.direction = tbl->direction;
2280 glb_res.resource_func = tbl->resource_func;
2281 glb_res.resource_type = tbl->resource_type;
2282 glb_res.glb_regfile_index = tbl->tbl_operand;
2284 case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE:
2285 if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) {
2286 BNXT_TF_DBG(ERR, "Template error, wrong fdb opcode\n");
2290 * get the index to write to from the global regfile and then
2293 if (ulp_mapper_glb_resource_read(parms->mapper_data,
2298 "Failed to get tbl idx from Global "
2303 index = tfp_be_to_cpu_64(regval);
2304 /* For external, we need to reverse shift */
2305 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2306 index = TF_ACT_REC_PTR_2_OFFSET(index);
2309 case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE:
2311 * The read is different from the rest and can be handled here
2312 * instead of trying to use common code. Simply read the table
2313 * with the index from the regfile, scan and store the
2314 * identifiers, and return.
2316 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2317 /* Not currently supporting with EXT */
2319 "Ext Table Read Opcode not supported.\n");
2322 if (!ulp_regfile_read(parms->regfile,
2323 tbl->tbl_operand, ®val)) {
2325 "Failed to get tbl idx from regfile[%d]\n",
2329 index = tfp_be_to_cpu_64(regval);
2330 gparms.dir = tbl->direction;
2331 gparms.type = tbl->resource_type;
2332 gparms.data = ulp_blob_data_get(&data, &tmplen);
2333 gparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tbl->result_bit_size);
2335 rc = tf_get_tbl_entry(tfp, &gparms);
2337 BNXT_TF_DBG(ERR, "Failed to read the tbl entry %d:%d\n",
2338 tbl->resource_type, index);
2342 * Scan the fields in the entry and push them into the regfile.
2344 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2346 gparms.data_sz_in_bytes,
2349 BNXT_TF_DBG(ERR, "Failed to read fields on tbl read "
2355 BNXT_TF_DBG(ERR, "Invalid index table opcode %d\n",
2361 /* Get the result fields list */
2362 rc = ulp_mapper_tbl_result_build(parms,
2367 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2373 aparms.dir = tbl->direction;
2374 aparms.type = tbl->resource_type;
2375 aparms.tbl_scope_id = tbl_scope_id;
2377 /* All failures after the alloc succeeds require a free */
2378 rc = tf_alloc_tbl_entry(tfp, &aparms);
2380 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2381 tf_tbl_type_2_str(tbl->resource_type),
2382 tf_dir_2_str(tbl->direction), rc);
2388 * Store the index in the regfile since we either allocated it
2391 * Calculate the idx for the result record, for external EM the
2392 * offset needs to be shifted accordingly.
2393 * If external non-inline table types are used then need to
2394 * revisit this logic.
2396 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2397 regval = TF_ACT_REC_OFFSET_2_PTR(index);
2400 regval = tfp_cpu_to_be_64(regval);
2403 rc = ulp_mapper_glb_resource_write(parms->mapper_data,
2406 rc = ulp_regfile_write(parms->regfile,
2407 tbl->tbl_operand, regval);
2411 "Failed to write %s regfile[%d] rc=%d\n",
2412 (global) ? "global" : "reg",
2413 tbl->tbl_operand, rc);
2419 sparms.dir = tbl->direction;
2420 sparms.type = tbl->resource_type;
2421 sparms.data = ulp_blob_data_get(&data, &tmplen);
2422 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2424 sparms.tbl_scope_id = tbl_scope_id;
2425 rc = tf_set_tbl_entry(tfp, &sparms);
2428 "Index table[%s][%s][%x] write failed "
2430 tf_tbl_type_2_str(sparms.type),
2431 tf_dir_2_str(sparms.dir),
2436 /* Calculate action record size */
2437 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2438 act_rec_size = (ULP_BITS_2_BYTE_NR(tmplen) + 15) / 16;
2440 if (ulp_regfile_write(parms->regfile,
2441 BNXT_ULP_RF_IDX_ACTION_REC_SIZE,
2442 tfp_cpu_to_be_64(act_rec_size)))
2444 "Failed write the act rec size\n");
2448 /* Link the resource to the flow in the flow db */
2449 memset(&fid_parms, 0, sizeof(fid_parms));
2450 fid_parms.direction = tbl->direction;
2451 fid_parms.resource_func = tbl->resource_func;
2452 fid_parms.resource_type = tbl->resource_type;
2453 fid_parms.resource_sub_type = tbl->resource_sub_type;
2454 fid_parms.resource_hndl = index;
2455 fid_parms.critical_resource = tbl->critical_resource;
2457 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2459 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
2464 /* Perform the VF rep action */
2465 rc = ulp_mapper_mark_vfr_idx_process(parms, tbl);
2467 BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc);
2473 * Free the allocated resource since we failed to either
2474 * write to the entry or link the flow
2476 free_parms.dir = tbl->direction;
2477 free_parms.type = tbl->resource_type;
2478 free_parms.idx = index;
2479 free_parms.tbl_scope_id = tbl_scope_id;
2481 trc = tf_free_tbl_entry(tfp, &free_parms);
2483 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
2489 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2490 struct bnxt_ulp_mapper_tbl_info *tbl)
2492 struct ulp_blob data, res_blob;
2496 struct tf_set_if_tbl_entry_parms iftbl_params = { 0 };
2497 struct tf_get_if_tbl_entry_parms get_parms = { 0 };
2498 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
2499 enum bnxt_ulp_if_tbl_opc if_opc = tbl->tbl_opcode;
2502 /* Initialize the blob data */
2503 if (!ulp_blob_init(&data, tbl->result_bit_size,
2504 parms->device_params->byte_order)) {
2505 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2509 /* create the result blob */
2510 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "IFtable Result");
2512 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2516 /* Get the index details */
2518 case BNXT_ULP_IF_TBL_OPC_WR_COMP_FIELD:
2519 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2521 case BNXT_ULP_IF_TBL_OPC_WR_REGFILE:
2522 if (!ulp_regfile_read(parms->regfile, tbl->tbl_operand, &idx)) {
2523 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2527 idx = tfp_be_to_cpu_64(idx);
2529 case BNXT_ULP_IF_TBL_OPC_WR_CONST:
2530 idx = tbl->tbl_operand;
2532 case BNXT_ULP_IF_TBL_OPC_RD_COMP_FIELD:
2533 /* Initialize the result blob */
2534 if (!ulp_blob_init(&res_blob, tbl->result_bit_size,
2535 parms->device_params->byte_order)) {
2536 BNXT_TF_DBG(ERR, "Failed initial result blob\n");
2540 /* read the interface table */
2541 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2542 res_size = ULP_BITS_2_BYTE(tbl->result_bit_size);
2543 get_parms.dir = tbl->direction;
2544 get_parms.type = tbl->resource_type;
2545 get_parms.idx = idx;
2546 get_parms.data = ulp_blob_data_get(&res_blob, &tmplen);
2547 get_parms.data_sz_in_bytes = res_size;
2549 rc = tf_get_if_tbl_entry(tfp, &get_parms);
2551 BNXT_TF_DBG(ERR, "Get table[%d][%s][%x] failed rc=%d\n",
2553 tf_dir_2_str(get_parms.dir),
2557 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2560 res_blob.byte_order);
2562 BNXT_TF_DBG(ERR, "Scan and extract failed rc=%d\n", rc);
2564 case BNXT_ULP_IF_TBL_OPC_NOT_USED:
2565 return rc; /* skip it */
2567 BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n");
2571 /* Perform the tf table set by filling the set params */
2572 iftbl_params.dir = tbl->direction;
2573 iftbl_params.type = tbl->resource_type;
2574 iftbl_params.data = ulp_blob_data_get(&data, &tmplen);
2575 iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2576 iftbl_params.idx = idx;
2578 rc = tf_set_if_tbl_entry(tfp, &iftbl_params);
2580 BNXT_TF_DBG(ERR, "Set table[%d][%s][%x] failed rc=%d\n",
2581 iftbl_params.type,/* TBD: add tf_if_tbl_2_str */
2582 tf_dir_2_str(iftbl_params.dir),
2583 iftbl_params.idx, rc);
2588 * TBD: Need to look at the need to store idx in flow db for restore
2589 * the table to its original state on deletion of this entry.
2595 ulp_mapper_gen_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2596 struct bnxt_ulp_mapper_tbl_info *tbl)
2598 struct ulp_mapper_gen_tbl_list *gen_tbl_list;
2599 struct bnxt_ulp_mapper_key_info *kflds;
2600 struct ulp_flow_db_res_params fid_parms;
2601 struct ulp_mapper_gen_tbl_entry gen_tbl_ent, *g;
2602 struct ulp_gen_hash_entry_params hash_entry;
2604 struct ulp_blob key, data;
2607 uint32_t i, num_kflds = 0, key_index = 0;
2608 uint32_t gen_tbl_miss = 1, fdb_write = 0;
2612 /* Get the key fields list and build the key. */
2613 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2614 if (!kflds || !num_kflds) {
2615 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2619 if (!ulp_blob_init(&key, tbl->key_bit_size,
2620 parms->device_params->byte_order)) {
2621 BNXT_TF_DBG(ERR, "Failed to alloc blob\n");
2624 for (i = 0; i < num_kflds; i++) {
2626 rc = ulp_mapper_field_process(parms, tbl->direction,
2627 &kflds[i].field_info_spec,
2628 &key, 1, "Gen Tbl Key");
2631 "Failed to create key for Gen tbl rc=%d\n",
2637 /* Calculate the table index for the generic table*/
2638 tbl_idx = ulp_mapper_gen_tbl_idx_calculate(tbl->resource_sub_type,
2641 BNXT_TF_DBG(ERR, "Invalid table index %x:%x\n",
2642 tbl->resource_sub_type, tbl->direction);
2646 /* The_key is a byte array convert it to a search index */
2647 cache_key = ulp_blob_data_get(&key, &tmplen);
2648 /* get the generic table */
2649 gen_tbl_list = &parms->mapper_data->gen_tbl_list[tbl_idx];
2651 /* Check if generic hash table */
2652 if (gen_tbl_list->hash_tbl) {
2653 if (tbl->gen_tbl_lkup_type !=
2654 BNXT_ULP_GENERIC_TBL_LKUP_TYPE_HASH) {
2655 BNXT_TF_DBG(ERR, "%s: Invalid template lkup type\n",
2656 gen_tbl_list->gen_tbl_name);
2659 hash_entry.key_data = cache_key;
2660 hash_entry.key_length = ULP_BITS_2_BYTE(tmplen);
2661 rc = ulp_gen_hash_tbl_list_key_search(gen_tbl_list->hash_tbl,
2664 BNXT_TF_DBG(ERR, "%s: hash tbl search failed\n",
2665 gen_tbl_list->gen_tbl_name);
2668 if (hash_entry.search_flag == ULP_GEN_HASH_SEARCH_FOUND) {
2669 key_index = hash_entry.key_idx;
2670 /* Get the generic table entry */
2671 if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list,
2675 /* store the hash index in the fdb */
2676 key_index = hash_entry.hash_index;
2679 /* convert key to index directly */
2680 memcpy(&key_index, cache_key, ULP_BITS_2_BYTE(tmplen));
2681 /* Get the generic table entry */
2682 if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list, key_index,
2686 switch (tbl->tbl_opcode) {
2687 case BNXT_ULP_GENERIC_TBL_OPC_READ:
2688 if (gen_tbl_list->hash_tbl) {
2689 if (hash_entry.search_flag != ULP_GEN_HASH_SEARCH_FOUND)
2690 break; /* nothing to be done , no entry */
2693 /* check the reference count */
2694 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2696 /* Scan ident list and create the result blob*/
2697 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2703 "Failed to scan ident list\n");
2706 if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) {
2707 /* increment the reference count */
2708 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2716 case BNXT_ULP_GENERIC_TBL_OPC_WRITE:
2717 if (gen_tbl_list->hash_tbl) {
2718 rc = ulp_mapper_gen_tbl_hash_entry_add(gen_tbl_list,
2723 /* store the hash index in the fdb */
2724 key_index = hash_entry.hash_index;
2726 /* check the reference count */
2727 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2728 /* a hit then error */
2729 BNXT_TF_DBG(ERR, "generic entry already present\n");
2730 return -EINVAL; /* success */
2733 /* Initialize the blob data */
2734 if (!ulp_blob_init(&data, tbl->result_bit_size,
2735 gen_tbl_ent.byte_order)) {
2736 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2740 /* Get the result fields list */
2741 rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
2744 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2747 byte_data = ulp_blob_data_get(&data, &tmplen);
2748 rc = ulp_mapper_gen_tbl_entry_data_set(&gen_tbl_ent,
2750 ULP_BITS_2_BYTE(tmplen));
2752 BNXT_TF_DBG(ERR, "Failed to write generic table\n");
2756 /* increment the reference count */
2757 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2759 parms->shared_hndl = (uint64_t)tbl_idx << 32 | key_index;
2762 BNXT_TF_DBG(ERR, "Invalid table opcode %x\n", tbl->tbl_opcode);
2766 /* Set the generic entry hit */
2767 rc = ulp_regfile_write(parms->regfile,
2768 BNXT_ULP_RF_IDX_GENERIC_TBL_MISS,
2769 tfp_cpu_to_be_64(gen_tbl_miss));
2771 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
2772 BNXT_ULP_RF_IDX_GENERIC_TBL_MISS);
2776 /* add the entry to the flow database */
2778 memset(&fid_parms, 0, sizeof(fid_parms));
2779 fid_parms.direction = tbl->direction;
2780 fid_parms.resource_func = tbl->resource_func;
2781 fid_parms.resource_sub_type = tbl->resource_sub_type;
2782 fid_parms.resource_hndl = key_index;
2783 fid_parms.critical_resource = tbl->critical_resource;
2784 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2786 BNXT_TF_DBG(ERR, "Fail to add gen ent flowdb %d\n", rc);
2792 ulp_mapper_ctrl_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2793 struct bnxt_ulp_mapper_tbl_info *tbl)
2797 /* process the fdb opcode for alloc push */
2798 if (tbl->fdb_opcode == BNXT_ULP_FDB_OPC_ALLOC_RID_REGFILE) {
2799 rc = ulp_mapper_fdb_opc_alloc_rid(parms, tbl);
2801 BNXT_TF_DBG(ERR, "Failed to do fdb alloc\n");
2809 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx,
2810 struct bnxt_ulp_mapper_data *mapper_data)
2812 struct bnxt_ulp_glb_resource_info *glb_res;
2813 uint32_t num_glb_res_ids, idx;
2816 glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids);
2817 if (!glb_res || !num_glb_res_ids) {
2818 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
2822 /* Iterate the global resources and process each one */
2823 for (idx = 0; idx < num_glb_res_ids; idx++) {
2824 switch (glb_res[idx].resource_func) {
2825 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
2826 rc = ulp_mapper_resource_ident_allocate(ulp_ctx,
2830 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2831 rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx,
2836 BNXT_TF_DBG(ERR, "Global resource %x not supported\n",
2837 glb_res[idx].resource_func);
2848 * Common conditional opcode process routine that is used for both the template
2849 * rejection and table conditional execution.
2852 ulp_mapper_cond_opc_process(struct bnxt_ulp_mapper_parms *parms,
2853 enum bnxt_ulp_cond_opc opc,
2857 enum bnxt_ulp_flow_mem_type mtype = BNXT_ULP_FLOW_MEM_TYPE_INT;
2863 case BNXT_ULP_COND_OPC_CF_IS_SET:
2864 if (operand < BNXT_ULP_CF_IDX_LAST) {
2865 *res = ULP_COMP_FLD_IDX_RD(parms, operand);
2867 BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
2872 case BNXT_ULP_COND_OPC_CF_NOT_SET:
2873 if (operand < BNXT_ULP_CF_IDX_LAST) {
2874 *res = !ULP_COMP_FLD_IDX_RD(parms, operand);
2876 BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
2881 case BNXT_ULP_COND_OPC_ACT_BIT_IS_SET:
2882 if (operand < BNXT_ULP_ACT_BIT_LAST) {
2883 *res = ULP_BITMAP_ISSET(parms->act_bitmap->bits,
2886 BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
2891 case BNXT_ULP_COND_OPC_ACT_BIT_NOT_SET:
2892 if (operand < BNXT_ULP_ACT_BIT_LAST) {
2893 *res = !ULP_BITMAP_ISSET(parms->act_bitmap->bits,
2896 BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
2901 case BNXT_ULP_COND_OPC_HDR_BIT_IS_SET:
2902 if (operand < BNXT_ULP_HDR_BIT_LAST) {
2903 *res = ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
2906 BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
2911 case BNXT_ULP_COND_OPC_HDR_BIT_NOT_SET:
2912 if (operand < BNXT_ULP_HDR_BIT_LAST) {
2913 *res = !ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
2916 BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
2921 case BNXT_ULP_COND_OPC_FIELD_BIT_IS_SET:
2922 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
2924 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
2928 *res = ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
2930 case BNXT_ULP_COND_OPC_FIELD_BIT_NOT_SET:
2931 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
2933 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
2937 *res = !ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
2939 case BNXT_ULP_COND_OPC_RF_IS_SET:
2940 if (!ulp_regfile_read(parms->regfile, operand, ®val)) {
2941 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
2946 case BNXT_ULP_COND_OPC_RF_NOT_SET:
2947 if (!ulp_regfile_read(parms->regfile, operand, ®val)) {
2948 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
2953 case BNXT_ULP_COND_OPC_FLOW_PAT_MATCH:
2954 if (parms->flow_pattern_id == operand) {
2955 BNXT_TF_DBG(ERR, "field pattern match failed %x\n",
2956 parms->flow_pattern_id);
2960 case BNXT_ULP_COND_OPC_ACT_PAT_MATCH:
2961 if (parms->act_pattern_id == operand) {
2962 BNXT_TF_DBG(ERR, "act pattern match failed %x\n",
2963 parms->act_pattern_id);
2967 case BNXT_ULP_COND_OPC_EXT_MEM_IS_SET:
2968 if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) {
2969 BNXT_TF_DBG(ERR, "Failed to get the mem type\n");
2972 *res = (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) ? 0 : 1;
2974 case BNXT_ULP_COND_OPC_EXT_MEM_NOT_SET:
2975 if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) {
2976 BNXT_TF_DBG(ERR, "Failed to get the mem type\n");
2979 *res = (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT) ? 1 : 0;
2982 BNXT_TF_DBG(ERR, "Invalid conditional opcode %d\n", opc);
2990 ulp_mapper_cc_upd_opr_compute(struct bnxt_ulp_mapper_parms *parms,
2992 enum bnxt_ulp_cc_upd_src cc_src,
3000 case BNXT_ULP_CC_UPD_SRC_COMP_FIELD:
3001 if (cc_opr >= BNXT_ULP_CF_IDX_LAST) {
3002 BNXT_TF_DBG(ERR, "invalid index %u\n", cc_opr);
3005 *result = (uint64_t)ULP_COMP_FLD_IDX_RD(parms, cc_opr);
3007 case BNXT_ULP_CC_UPD_SRC_REGFILE:
3008 if (!ulp_regfile_read(parms->regfile, cc_opr, ®val)) {
3009 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", cc_opr);
3012 *result = tfp_be_to_cpu_64(regval);
3014 case BNXT_ULP_CC_UPD_SRC_GLB_REGFILE:
3015 if (ulp_mapper_glb_resource_read(parms->mapper_data, dir,
3017 BNXT_TF_DBG(ERR, "global regfile[%d] read failed.\n",
3021 *result = tfp_be_to_cpu_64(regval);
3024 BNXT_TF_DBG(ERR, "invalid src code %u\n", cc_src);
3031 ulp_mapper_cc_upd_info_process(struct bnxt_ulp_mapper_parms *parms,
3032 struct bnxt_ulp_mapper_tbl_info *tbl)
3034 struct bnxt_ulp_mapper_cc_upd_info *cc_upd = &tbl->cc_upd_info;
3035 uint64_t res = 0, res1, res2;
3038 if (cc_upd->cc_opc == BNXT_ULP_CC_UPD_OPC_NOP)
3041 rc = ulp_mapper_cc_upd_opr_compute(parms, tbl->direction,
3043 cc_upd->cc_opr1, &res1);
3047 rc = ulp_mapper_cc_upd_opr_compute(parms, tbl->direction,
3049 cc_upd->cc_opr2, &res2);
3053 switch (cc_upd->cc_opc) {
3054 case BNXT_ULP_CC_UPD_OPC_NOP:
3057 case BNXT_ULP_CC_UPD_OPC_EQ:
3061 case BNXT_ULP_CC_UPD_OPC_NE:
3065 case BNXT_ULP_CC_UPD_OPC_GE:
3069 case BNXT_ULP_CC_UPD_OPC_GT:
3073 case BNXT_ULP_CC_UPD_OPC_LE:
3077 case BNXT_ULP_CC_UPD_OPC_LT:
3081 case BNXT_ULP_CC_UPD_OPC_LAST:
3082 BNXT_TF_DBG(ERR, "invalid code %u\n", cc_upd->cc_opc);
3085 if (ulp_regfile_write(parms->regfile, cc_upd->cc_dst_opr,
3086 tfp_cpu_to_be_64(res))) {
3087 BNXT_TF_DBG(ERR, "Failed write the cc_opc %u\n",
3088 cc_upd->cc_dst_opr);
3097 * Processes a list of conditions and returns both a status and result of the
3098 * list. The status must be checked prior to verifying the result.
3100 * returns 0 for success, negative on failure
3101 * returns res = 1 for true, res = 0 for false.
3104 ulp_mapper_cond_opc_list_process(struct bnxt_ulp_mapper_parms *parms,
3105 enum bnxt_ulp_cond_list_opc list_opc,
3106 struct bnxt_ulp_mapper_cond_info *list,
3111 int32_t rc = 0, trc = 0;
3114 case BNXT_ULP_COND_LIST_OPC_AND:
3115 /* AND Defaults to true. */
3118 case BNXT_ULP_COND_LIST_OPC_OR:
3119 /* OR Defaults to false. */
3122 case BNXT_ULP_COND_LIST_OPC_TRUE:
3125 case BNXT_ULP_COND_LIST_OPC_FALSE:
3129 BNXT_TF_DBG(ERR, "Invalid conditional list opcode %d\n",
3135 for (i = 0; i < num; i++) {
3136 rc = ulp_mapper_cond_opc_process(parms,
3137 list[i].cond_opcode,
3138 list[i].cond_operand,
3143 if (list_opc == BNXT_ULP_COND_LIST_OPC_AND) {
3144 /* early return if result is ever zero */
3150 /* early return if result is ever non-zero */
3162 * Processes conflict resolution and returns both a status and result.
3163 * The status must be checked prior to verifying the result.
3165 * returns 0 for success, negative on failure
3166 * returns res = 1 for true, res = 0 for false.
3169 ulp_mapper_conflict_resolution_process(struct bnxt_ulp_mapper_parms *parms,
3170 struct bnxt_ulp_mapper_tbl_info *tbl,
3175 uint64_t comp_sig_id;
3178 switch (tbl->accept_opcode) {
3179 case BNXT_ULP_ACCEPT_OPC_ALWAYS:
3182 case BNXT_ULP_ACCEPT_OPC_FLOW_SIG_ID_MATCH:
3183 /* perform the signature validation*/
3184 if (tbl->resource_func ==
3185 BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE) {
3186 /* Perform the check that generic table is hit or not */
3187 if (!ulp_regfile_read(parms->regfile,
3188 BNXT_ULP_RF_IDX_GENERIC_TBL_MISS,
3190 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
3191 BNXT_ULP_RF_IDX_GENERIC_TBL_MISS);
3195 /* not a hit so no need to check flow sign*/
3200 /* compare the new flow signature against stored one */
3201 if (!ulp_regfile_read(parms->regfile,
3202 BNXT_ULP_RF_IDX_FLOW_SIG_ID,
3204 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
3205 BNXT_ULP_RF_IDX_FLOW_SIG_ID);
3208 comp_sig_id = ULP_COMP_FLD_IDX_RD(parms,
3209 BNXT_ULP_CF_IDX_FLOW_SIG_ID);
3210 regval = tfp_be_to_cpu_64(regval);
3211 if (comp_sig_id == regval)
3214 BNXT_TF_DBG(ERR, "failed signature match %x:%x\n",
3215 (uint32_t)comp_sig_id, (uint32_t)regval);
3218 BNXT_TF_DBG(ERR, "Invalid accept opcode %d\n",
3219 tbl->accept_opcode);
3226 ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid)
3228 struct bnxt_ulp_mapper_cond_info *cond_tbls = NULL;
3229 enum bnxt_ulp_cond_list_opc cond_opc;
3230 struct bnxt_ulp_mapper_tbl_info *tbls;
3231 struct bnxt_ulp_mapper_tbl_info *tbl;
3232 uint32_t num_tbls, tbl_idx, num_cond_tbls;
3233 int32_t rc = -EINVAL, cond_rc = 0;
3234 int32_t cond_goto = 1;
3236 cond_tbls = ulp_mapper_tmpl_reject_list_get(parms, tid,
3240 * Process the reject list if exists, otherwise assume that the
3241 * template is allowed.
3243 if (cond_tbls && num_cond_tbls) {
3244 rc = ulp_mapper_cond_opc_list_process(parms,
3252 /* Reject the template if True */
3254 BNXT_TF_DBG(ERR, "%s Template %d rejected.\n",
3255 ulp_mapper_tmpl_name_str(parms->tmpl_type),
3261 tbls = ulp_mapper_tbl_list_get(parms, tid, &num_tbls);
3262 if (!tbls || !num_tbls) {
3263 BNXT_TF_DBG(ERR, "No %s tables for %d:%d\n",
3264 ulp_mapper_tmpl_name_str(parms->tmpl_type),
3265 parms->dev_id, tid);
3269 for (tbl_idx = 0; tbl_idx < num_tbls && cond_goto;) {
3270 tbl = &tbls[tbl_idx];
3271 /* Process the conditional code update opcodes */
3272 if (ulp_mapper_cc_upd_info_process(parms, tbl)) {
3273 BNXT_TF_DBG(ERR, "Failed to process cond update\n");
3278 cond_tbls = ulp_mapper_tbl_execute_list_get(parms, tbl,
3281 rc = ulp_mapper_cond_opc_list_process(parms, cond_opc,
3282 cond_tbls, num_cond_tbls,
3285 BNXT_TF_DBG(ERR, "Failed to process cond opc list "
3289 /* Skip the table if False */
3291 cond_goto = tbl->execute_info.cond_false_goto;
3292 goto next_iteration;
3295 switch (tbl->resource_func) {
3296 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
3297 rc = ulp_mapper_tcam_tbl_process(parms, tbl);
3299 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
3300 rc = ulp_mapper_em_tbl_process(parms, tbl);
3302 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3303 rc = ulp_mapper_index_tbl_process(parms, tbl);
3305 case BNXT_ULP_RESOURCE_FUNC_IF_TABLE:
3306 rc = ulp_mapper_if_tbl_process(parms, tbl);
3308 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
3309 rc = ulp_mapper_gen_tbl_process(parms, tbl);
3311 case BNXT_ULP_RESOURCE_FUNC_CTRL_TABLE:
3312 rc = ulp_mapper_ctrl_tbl_process(parms, tbl);
3314 case BNXT_ULP_RESOURCE_FUNC_INVALID:
3318 BNXT_TF_DBG(ERR, "Unexpected mapper resource %d\n",
3319 tbl->resource_func);
3325 BNXT_TF_DBG(ERR, "Resource type %d failed\n",
3326 tbl->resource_func);
3330 /* perform the post table process */
3331 rc = ulp_mapper_conflict_resolution_process(parms, tbl,
3333 if (rc || !cond_rc) {
3334 BNXT_TF_DBG(ERR, "Failed due to conflict resolution\n");
3339 if (cond_goto == BNXT_ULP_COND_GOTO_REJECT) {
3340 BNXT_TF_DBG(ERR, "reject the flow\n");
3343 } else if (cond_goto & BNXT_ULP_COND_GOTO_RF) {
3347 /* least significant 16 bits from reg_file index */
3348 rf_idx = (uint32_t)(cond_goto & 0xFFFF);
3349 if (!ulp_regfile_read(parms->regfile, rf_idx,
3351 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
3356 cond_goto = (int32_t)regval;
3359 if (cond_goto < 0 && ((int32_t)tbl_idx + cond_goto) < 0) {
3360 BNXT_TF_DBG(ERR, "invalid conditional goto %d\n",
3364 tbl_idx += cond_goto;
3369 BNXT_TF_DBG(ERR, "%s tables failed creation for %d:%d\n",
3370 ulp_mapper_tmpl_name_str(parms->tmpl_type),
3371 parms->dev_id, tid);
3376 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
3378 struct ulp_flow_db_res_params *res)
3384 BNXT_TF_DBG(ERR, "Unable to free resource\n ");
3388 tfp = bnxt_ulp_cntxt_tfp_get(ulp);
3390 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
3394 switch (res->resource_func) {
3395 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
3396 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
3398 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
3399 rc = ulp_mapper_em_entry_free(ulp, tfp, res);
3401 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3402 rc = ulp_mapper_index_entry_free(ulp, tfp, res);
3404 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
3405 rc = ulp_mapper_ident_free(ulp, tfp, res);
3407 case BNXT_ULP_RESOURCE_FUNC_HW_FID:
3408 rc = ulp_mapper_mark_free(ulp, res);
3410 case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW:
3411 rc = ulp_mapper_parent_flow_free(ulp, fid, res);
3413 case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW:
3414 rc = ulp_mapper_child_flow_free(ulp, fid, res);
3416 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
3417 rc = ulp_mapper_gen_tbl_res_free(ulp, res);
3427 ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx,
3428 enum bnxt_ulp_fdb_type flow_type,
3431 struct ulp_flow_db_res_params res_parms = { 0 };
3435 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
3440 * Set the critical resource on the first resource del, then iterate
3441 * while status is good
3443 if (flow_type != BNXT_ULP_FDB_TYPE_RID)
3444 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES;
3446 rc = ulp_flow_db_resource_del(ulp_ctx, flow_type, fid, &res_parms);
3450 * This is unexpected on the first call to resource del.
3451 * It likely means that the flow did not exist in the flow db.
3453 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
3454 flow_type, fid, rc);
3459 trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms);
3462 * On fail, we still need to attempt to free the
3463 * remaining resources. Don't return
3466 "Flow[%d][0x%x] Res[%d][0x%016" PRIX64
3467 "] failed rc=%d.\n",
3468 flow_type, fid, res_parms.resource_func,
3469 res_parms.resource_hndl, trc);
3471 /* All subsequent call require the non-critical_resource */
3472 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
3474 rc = ulp_flow_db_resource_del(ulp_ctx,
3480 /* Free the Flow ID since we've removed all resources */
3481 rc = ulp_flow_db_fid_free(ulp_ctx, flow_type, fid);
3487 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx,
3488 struct bnxt_ulp_mapper_data *mapper_data)
3490 struct bnxt_ulp_mapper_glb_resource_entry *ent;
3491 struct ulp_flow_db_res_params res;
3494 /* Iterate the global resources and process each one */
3495 for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) {
3496 for (idx = 0; idx < BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
3498 ent = &mapper_data->glb_res_tbl[dir][idx];
3499 if (ent->resource_func ==
3500 BNXT_ULP_RESOURCE_FUNC_INVALID)
3502 memset(&res, 0, sizeof(struct ulp_flow_db_res_params));
3503 res.resource_func = ent->resource_func;
3504 res.direction = dir;
3505 res.resource_type = ent->resource_type;
3506 /*convert it from BE to cpu */
3508 tfp_be_to_cpu_64(ent->resource_hndl);
3509 ulp_mapper_resource_free(ulp_ctx, 0, &res);
3515 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx,
3516 enum bnxt_ulp_fdb_type flow_type,
3522 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
3526 rc = ulp_mapper_resources_free(ulp_ctx, flow_type, fid);
3530 /* Function to handle the mapping of the Flow to be compatible
3531 * with the underlying hardware.
3534 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
3535 struct bnxt_ulp_mapper_create_parms *cparms)
3537 struct bnxt_ulp_mapper_parms parms;
3538 struct ulp_regfile regfile;
3539 int32_t rc = 0, trc;
3541 if (!ulp_ctx || !cparms)
3544 /* Initialize the parms structure */
3545 memset(&parms, 0, sizeof(parms));
3546 parms.act_prop = cparms->act_prop;
3547 parms.act_bitmap = cparms->act;
3548 parms.hdr_bitmap = cparms->hdr_bitmap;
3549 parms.regfile = ®file;
3550 parms.hdr_field = cparms->hdr_field;
3551 parms.fld_bitmap = cparms->fld_bitmap;
3552 parms.comp_fld = cparms->comp_fld;
3553 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3554 parms.ulp_ctx = ulp_ctx;
3555 parms.act_tid = cparms->act_tid;
3556 parms.class_tid = cparms->class_tid;
3557 parms.flow_type = cparms->flow_type;
3558 parms.parent_flow = cparms->parent_flow;
3559 parms.parent_fid = cparms->parent_fid;
3560 parms.fid = cparms->flow_id;
3561 parms.tun_idx = cparms->tun_idx;
3562 parms.app_priority = cparms->app_priority;
3563 parms.flow_pattern_id = cparms->flow_pattern_id;
3564 parms.act_pattern_id = cparms->act_pattern_id;
3566 /* Get the device id from the ulp context */
3567 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
3568 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
3572 /* Get the device params, it will be used in later processing */
3573 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
3574 if (!parms.device_params) {
3575 BNXT_TF_DBG(ERR, "No device parms for device id %d\n",
3581 * Get the mapper data for dynamic mapper data such as default
3584 parms.mapper_data = (struct bnxt_ulp_mapper_data *)
3585 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3586 if (!parms.mapper_data) {
3587 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
3591 /* initialize the registry file for further processing */
3592 if (!ulp_regfile_init(parms.regfile)) {
3593 BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
3597 /* Process the action template list from the selected action table*/
3598 if (parms.act_tid) {
3599 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_ACTION;
3600 /* Process the action template tables */
3601 rc = ulp_mapper_tbls_process(&parms, parms.act_tid);
3604 cparms->shared_hndl = parms.shared_hndl;
3607 if (parms.class_tid) {
3608 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
3610 /* Process the class template tables.*/
3611 rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
3616 /* setup the parent-child details */
3617 if (parms.parent_flow) {
3618 /* create a parent flow details */
3619 rc = ulp_flow_db_parent_flow_create(&parms);
3622 } else if (parms.parent_fid) {
3623 /* create a child flow details */
3624 rc = ulp_flow_db_child_flow_create(&parms);
3632 /* Free all resources that were allocated during flow creation */
3633 trc = ulp_mapper_flow_destroy(ulp_ctx, parms.flow_type,
3636 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
3642 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx)
3644 struct bnxt_ulp_mapper_data *data;
3651 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3655 data = rte_zmalloc("ulp_mapper_data",
3656 sizeof(struct bnxt_ulp_mapper_data), 0);
3658 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n");
3662 if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) {
3663 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n");
3664 /* Don't call deinit since the prof_func wasn't allocated. */
3669 /* Allocate the global resource ids */
3670 rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data);
3672 BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n");
3676 /* Allocate the generic table list */
3677 rc = ulp_mapper_generic_tbl_list_init(data);
3679 BNXT_TF_DBG(ERR, "Failed to initialize generic tbl list\n");
3685 /* Ignore the return code in favor of returning the original error. */
3686 ulp_mapper_deinit(ulp_ctx);
3691 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx)
3693 struct bnxt_ulp_mapper_data *data;
3698 "Failed to acquire ulp context, so data may "
3699 "not be released.\n");
3703 data = (struct bnxt_ulp_mapper_data *)
3704 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3706 /* Go ahead and return since there is no allocated data. */
3707 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n");
3711 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3713 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n");
3714 /* Free the mapper data regardless of errors. */
3715 goto free_mapper_data;
3718 /* Free the global resource info table entries */
3719 ulp_mapper_glb_resource_info_deinit(ulp_ctx, data);
3722 /* Free the generic table */
3723 (void)ulp_mapper_generic_tbl_list_deinit(data);
3726 /* Reset the data pointer within the ulp_ctx. */
3727 bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL);