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);
203 /* Retrieve the global template table */
205 ulp_mapper_glb_template_table_get(uint32_t *num_entries)
209 *num_entries = BNXT_ULP_GLB_TEMPLATE_TBL_MAX_SZ;
210 return ulp_glb_template_tbl;
214 ulp_mapper_glb_field_tbl_get(struct bnxt_ulp_mapper_parms *parms,
220 t_idx = parms->class_tid << (BNXT_ULP_HDR_SIG_ID_SHIFT +
221 BNXT_ULP_GLB_FIELD_TBL_SHIFT);
222 t_idx += ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_HDR_SIG_ID) <<
223 BNXT_ULP_GLB_FIELD_TBL_SHIFT;
226 if (t_idx >= BNXT_ULP_GLB_FIELD_TBL_SIZE) {
227 BNXT_TF_DBG(ERR, "Invalid hdr field index %x:%x:%x\n",
228 parms->class_tid, t_idx, operand);
230 return -EINVAL; /* error */
232 *val = ulp_glb_field_tbl[t_idx];
237 * Get the size of the action property for a given index.
239 * idx [in] The index for the action property
241 * returns the size of the action property.
244 ulp_mapper_act_prop_size_get(uint32_t idx)
246 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST)
248 return ulp_act_prop_map_table[idx];
251 static struct bnxt_ulp_mapper_cond_info *
252 ulp_mapper_tmpl_reject_list_get(struct bnxt_ulp_mapper_parms *mparms,
255 enum bnxt_ulp_cond_list_opc *opc)
258 const struct bnxt_ulp_template_device_tbls *dev_tbls;
260 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
261 *num_tbls = dev_tbls->tmpl_list[tid].reject_info.cond_nums;
262 *opc = dev_tbls->tmpl_list[tid].reject_info.cond_list_opcode;
263 idx = dev_tbls->tmpl_list[tid].reject_info.cond_start_idx;
265 return &dev_tbls->cond_list[idx];
268 static struct bnxt_ulp_mapper_cond_info *
269 ulp_mapper_tbl_execute_list_get(struct bnxt_ulp_mapper_parms *mparms,
270 struct bnxt_ulp_mapper_tbl_info *tbl,
272 enum bnxt_ulp_cond_list_opc *opc)
275 const struct bnxt_ulp_template_device_tbls *dev_tbls;
277 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
278 *num_tbls = tbl->execute_info.cond_nums;
279 *opc = tbl->execute_info.cond_list_opcode;
280 idx = tbl->execute_info.cond_start_idx;
282 return &dev_tbls->cond_list[idx];
286 * Get a list of classifier tables that implement the flow
287 * Gets a device dependent list of tables that implement the class template id
289 * mparms [in] The mappers parms with data related to the flow.
291 * tid [in] The template id that matches the flow
293 * num_tbls [out] The number of classifier tables in the returned array
295 * returns An array of classifier tables to implement the flow, or NULL on
298 static struct bnxt_ulp_mapper_tbl_info *
299 ulp_mapper_tbl_list_get(struct bnxt_ulp_mapper_parms *mparms,
304 const struct bnxt_ulp_template_device_tbls *dev_tbls;
306 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
308 idx = dev_tbls->tmpl_list[tid].start_tbl_idx;
309 *num_tbls = dev_tbls->tmpl_list[tid].num_tbls;
311 return &dev_tbls->tbl_list[idx];
315 * Get the list of key fields that implement the flow.
317 * mparms [in] The mapper parms with information about the flow
319 * tbl [in] A single table instance to get the key fields from
321 * num_flds [out] The number of key fields in the returned array
323 * Returns array of Key fields, or NULL on error.
325 static struct bnxt_ulp_mapper_key_info *
326 ulp_mapper_key_fields_get(struct bnxt_ulp_mapper_parms *mparms,
327 struct bnxt_ulp_mapper_tbl_info *tbl,
331 const struct bnxt_ulp_template_device_tbls *dev_tbls;
333 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
334 if (!dev_tbls->key_info_list) {
339 idx = tbl->key_start_idx;
340 *num_flds = tbl->key_num_fields;
342 return &dev_tbls->key_info_list[idx];
346 * Get the list of data fields that implement the flow.
348 * mparms [in] The mapper parms with information about the flow
350 * tbl [in] A single table instance to get the data fields from
352 * num_flds [out] The number of data fields in the returned array.
354 * num_encap_flds [out] The number of encap fields in the returned array.
356 * Returns array of data fields, or NULL on error.
358 static struct bnxt_ulp_mapper_field_info *
359 ulp_mapper_result_fields_get(struct bnxt_ulp_mapper_parms *mparms,
360 struct bnxt_ulp_mapper_tbl_info *tbl,
362 uint32_t *num_encap_flds)
365 const struct bnxt_ulp_template_device_tbls *dev_tbls;
367 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
368 if (!dev_tbls->result_field_list) {
374 idx = tbl->result_start_idx;
375 *num_flds = tbl->result_num_fields;
376 *num_encap_flds = tbl->encap_num_fields;
378 return &dev_tbls->result_field_list[idx];
382 * Get the list of ident fields that implement the flow
384 * tbl [in] A single table instance to get the ident fields from
386 * num_flds [out] The number of ident fields in the returned array
388 * returns array of ident fields, or NULL on error
390 static struct bnxt_ulp_mapper_ident_info *
391 ulp_mapper_ident_fields_get(struct bnxt_ulp_mapper_parms *mparms,
392 struct bnxt_ulp_mapper_tbl_info *tbl,
396 const struct bnxt_ulp_template_device_tbls *dev_tbls;
398 dev_tbls = &mparms->device_params->dev_tbls[mparms->tmpl_type];
399 if (!dev_tbls->ident_list) {
404 idx = tbl->ident_start_idx;
405 *num_flds = tbl->ident_nums;
407 return &dev_tbls->ident_list[idx];
410 static inline int32_t
411 ulp_mapper_tcam_entry_free(struct bnxt_ulp_context *ulp __rte_unused,
413 struct ulp_flow_db_res_params *res)
415 struct tf_free_tcam_entry_parms fparms = {
416 .dir = res->direction,
417 .tcam_tbl_type = res->resource_type,
418 .idx = (uint16_t)res->resource_hndl
421 return tf_free_tcam_entry(tfp, &fparms);
424 static inline int32_t
425 ulp_mapper_index_entry_free(struct bnxt_ulp_context *ulp,
427 struct ulp_flow_db_res_params *res)
429 struct tf_free_tbl_entry_parms fparms = {
430 .dir = res->direction,
431 .type = res->resource_type,
432 .idx = (uint32_t)res->resource_hndl
436 * Just get the table scope, it will be ignored if not necessary
437 * by the tf_free_tbl_entry
439 (void)bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
441 return tf_free_tbl_entry(tfp, &fparms);
444 static inline int32_t
445 ulp_mapper_em_entry_free(struct bnxt_ulp_context *ulp,
447 struct ulp_flow_db_res_params *res)
449 struct tf_delete_em_entry_parms fparms = { 0 };
452 fparms.dir = res->direction;
453 fparms.flow_handle = res->resource_hndl;
455 rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp, &fparms.tbl_scope_id);
457 BNXT_TF_DBG(ERR, "Failed to get table scope\n");
461 return tf_delete_em_entry(tfp, &fparms);
464 static inline int32_t
465 ulp_mapper_ident_free(struct bnxt_ulp_context *ulp __rte_unused,
467 struct ulp_flow_db_res_params *res)
469 struct tf_free_identifier_parms fparms = {
470 .dir = res->direction,
471 .ident_type = res->resource_type,
472 .id = (uint16_t)res->resource_hndl
475 return tf_free_identifier(tfp, &fparms);
478 static inline int32_t
479 ulp_mapper_mark_free(struct bnxt_ulp_context *ulp,
480 struct ulp_flow_db_res_params *res)
482 return ulp_mark_db_mark_del(ulp,
487 static inline int32_t
488 ulp_mapper_parent_flow_free(struct bnxt_ulp_context *ulp,
490 struct ulp_flow_db_res_params *res)
492 uint32_t idx, child_fid = 0, parent_idx;
493 struct bnxt_ulp_flow_db *flow_db;
495 parent_idx = (uint32_t)res->resource_hndl;
497 /* check the validity of the parent fid */
498 if (ulp_flow_db_parent_flow_idx_get(ulp, parent_fid, &idx) ||
500 BNXT_TF_DBG(ERR, "invalid parent flow id %x\n", parent_fid);
504 /* Clear all the child flows parent index */
505 flow_db = bnxt_ulp_cntxt_ptr2_flow_db_get(ulp);
506 while (!ulp_flow_db_parent_child_flow_next_entry_get(flow_db, idx,
508 /* update the child flows resource handle */
509 if (ulp_flow_db_child_flow_reset(ulp, BNXT_ULP_FDB_TYPE_REGULAR,
511 BNXT_TF_DBG(ERR, "failed to reset child flow %x\n",
517 /* free the parent entry in the parent table flow */
518 if (ulp_flow_db_parent_flow_free(ulp, parent_fid)) {
519 BNXT_TF_DBG(ERR, "failed to free parent flow %x\n", parent_fid);
525 static inline int32_t
526 ulp_mapper_child_flow_free(struct bnxt_ulp_context *ulp,
528 struct ulp_flow_db_res_params *res)
532 parent_fid = (uint32_t)res->resource_hndl;
534 return 0; /* Already freed - orphan child*/
536 /* reset the child flow bitset*/
537 if (ulp_flow_db_parent_child_flow_set(ulp, parent_fid, child_fid, 0)) {
538 BNXT_TF_DBG(ERR, "error in resetting child flow bitset %x:%x\n",
539 parent_fid, child_fid);
546 * Process the flow database opcode alloc action.
547 * returns 0 on success
550 ulp_mapper_fdb_opc_alloc_rid(struct bnxt_ulp_mapper_parms *parms,
551 struct bnxt_ulp_mapper_tbl_info *tbl)
557 /* allocate a new fid */
558 rc = ulp_flow_db_fid_alloc(parms->ulp_ctx,
559 BNXT_ULP_FDB_TYPE_RID,
563 "Unable to allocate flow table entry\n");
566 /* Store the allocated fid in regfile*/
568 rc = ulp_regfile_write(parms->regfile, tbl->fdb_operand,
569 tfp_cpu_to_be_64(val64));
571 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
573 ulp_flow_db_fid_free(parms->ulp_ctx,
574 BNXT_ULP_FDB_TYPE_RID, rid);
581 * Process the flow database opcode action.
582 * returns 0 on success.
585 ulp_mapper_fdb_opc_process(struct bnxt_ulp_mapper_parms *parms,
586 struct bnxt_ulp_mapper_tbl_info *tbl,
587 struct ulp_flow_db_res_params *fid_parms)
591 enum bnxt_ulp_fdb_type flow_type;
594 switch (tbl->fdb_opcode) {
595 case BNXT_ULP_FDB_OPC_PUSH_FID:
596 push_fid = parms->fid;
597 flow_type = parms->flow_type;
599 case BNXT_ULP_FDB_OPC_PUSH_RID_REGFILE:
600 /* get the fid from the regfile */
601 rc = ulp_regfile_read(parms->regfile, tbl->fdb_operand,
604 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
608 /* Use the extracted fid to update the flow resource */
609 push_fid = (uint32_t)tfp_be_to_cpu_64(val64);
610 flow_type = BNXT_ULP_FDB_TYPE_RID;
613 return rc; /* Nothing to be done */
616 /* Add the resource to the flow database */
617 rc = ulp_flow_db_resource_add(parms->ulp_ctx, flow_type,
618 push_fid, fid_parms);
620 BNXT_TF_DBG(ERR, "Failed to add res to flow %x rc = %d\n",
626 * Process the flow database opcode action.
627 * returns 0 on success.
630 ulp_mapper_priority_opc_process(struct bnxt_ulp_mapper_parms *parms,
631 struct bnxt_ulp_mapper_tbl_info *tbl,
636 switch (tbl->pri_opcode) {
637 case BNXT_ULP_PRI_OPC_NOT_USED:
640 case BNXT_ULP_PRI_OPC_CONST:
641 *priority = tbl->pri_operand;
643 case BNXT_ULP_PRI_OPC_APP_PRI:
644 *priority = parms->app_priority;
647 BNXT_TF_DBG(ERR, "Priority opcode not supported %d\n",
656 * Process the identifier list in the given table.
657 * Extract the ident from the table entry and
658 * write it to the reg file.
659 * returns 0 on success.
662 ulp_mapper_tbl_ident_scan_ext(struct bnxt_ulp_mapper_parms *parms,
663 struct bnxt_ulp_mapper_tbl_info *tbl,
665 uint32_t byte_data_size,
666 enum bnxt_ulp_byte_order byte_order)
668 struct bnxt_ulp_mapper_ident_info *idents;
669 uint32_t i, num_idents = 0;
672 /* validate the null arguments */
674 BNXT_TF_DBG(ERR, "invalid argument\n");
678 /* Get the ident list and process each one */
679 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
681 for (i = 0; i < num_idents; i++) {
682 /* check the size of the buffer for validation */
683 if ((idents[i].ident_bit_pos + idents[i].ident_bit_size) >
684 ULP_BYTE_2_BITS(byte_data_size) ||
685 idents[i].ident_bit_size > ULP_BYTE_2_BITS(sizeof(val64))) {
686 BNXT_TF_DBG(ERR, "invalid offset or length %x:%x:%x\n",
687 idents[i].ident_bit_pos,
688 idents[i].ident_bit_size,
693 if (byte_order == BNXT_ULP_BYTE_ORDER_LE)
694 ulp_bs_pull_lsb(byte_data, (uint8_t *)&val64,
696 idents[i].ident_bit_pos,
697 idents[i].ident_bit_size);
699 ulp_bs_pull_msb(byte_data, (uint8_t *)&val64,
700 idents[i].ident_bit_pos,
701 idents[i].ident_bit_size);
703 /* Write it to the regfile, val64 is already in big-endian*/
704 if (ulp_regfile_write(parms->regfile,
705 idents[i].regfile_idx, val64)) {
706 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
707 idents[i].regfile_idx);
715 * Process the identifier instruction and either store it in the flow database
716 * or return it in the val (if not NULL) on success. If val is NULL, the
717 * identifier is to be stored in the flow database.
720 ulp_mapper_ident_process(struct bnxt_ulp_mapper_parms *parms,
721 struct bnxt_ulp_mapper_tbl_info *tbl,
722 struct bnxt_ulp_mapper_ident_info *ident,
725 struct ulp_flow_db_res_params fid_parms;
728 struct tf_alloc_identifier_parms iparms = { 0 };
729 struct tf_free_identifier_parms free_parms = { 0 };
733 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
735 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
739 idx = ident->regfile_idx;
741 iparms.ident_type = ident->ident_type;
742 iparms.dir = tbl->direction;
744 rc = tf_alloc_identifier(tfp, &iparms);
746 BNXT_TF_DBG(ERR, "Alloc ident %s:%s failed.\n",
747 tf_dir_2_str(iparms.dir),
748 tf_ident_2_str(iparms.ident_type));
752 id = (uint64_t)tfp_cpu_to_be_64(iparms.id);
753 if (ulp_regfile_write(parms->regfile, idx, id)) {
754 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
756 /* Need to free the identifier, so goto error */
760 /* Link the resource to the flow in the flow db */
762 memset(&fid_parms, 0, sizeof(fid_parms));
763 fid_parms.direction = tbl->direction;
764 fid_parms.resource_func = ident->resource_func;
765 fid_parms.resource_type = ident->ident_type;
766 fid_parms.resource_hndl = iparms.id;
767 fid_parms.critical_resource = tbl->critical_resource;
769 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
771 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
773 /* Need to free the identifier, so goto error */
782 /* Need to free the identifier */
783 free_parms.dir = tbl->direction;
784 free_parms.ident_type = ident->ident_type;
785 free_parms.id = iparms.id;
787 (void)tf_free_identifier(tfp, &free_parms);
789 BNXT_TF_DBG(ERR, "Ident process failed for %s:%s\n",
791 tf_dir_2_str(tbl->direction));
796 * Process the identifier instruction and extract it from result blob.
797 * Increment the identifier reference count and store it in the flow database.
800 ulp_mapper_ident_extract(struct bnxt_ulp_mapper_parms *parms,
801 struct bnxt_ulp_mapper_tbl_info *tbl,
802 struct bnxt_ulp_mapper_ident_info *ident,
803 struct ulp_blob *res_blob)
805 struct ulp_flow_db_res_params fid_parms;
808 struct tf_search_identifier_parms sparms = { 0 };
809 struct tf_free_identifier_parms free_parms = { 0 };
813 /* Get the tfp from ulp context */
814 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
816 BNXT_TF_DBG(ERR, "Failed to get tf pointer\n");
820 /* Extract the index from the result blob */
821 rc = ulp_blob_pull(res_blob, (uint8_t *)&idx, sizeof(idx),
822 ident->ident_bit_pos, ident->ident_bit_size);
824 BNXT_TF_DBG(ERR, "Failed to extract identifier from blob\n");
828 /* populate the search params and search identifier shadow table */
829 sparms.ident_type = ident->ident_type;
830 sparms.dir = tbl->direction;
831 /* convert the idx into cpu format */
832 sparms.search_id = tfp_be_to_cpu_32(idx);
834 /* Search identifier also increase the reference count */
835 rc = tf_search_identifier(tfp, &sparms);
837 BNXT_TF_DBG(ERR, "Search ident %s:%s:%x failed.\n",
838 tf_dir_2_str(sparms.dir),
839 tf_ident_2_str(sparms.ident_type),
844 /* Write it to the regfile */
845 id = (uint64_t)tfp_cpu_to_be_64(sparms.search_id);
846 if (ulp_regfile_write(parms->regfile, ident->regfile_idx, id)) {
847 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n", idx);
849 /* Need to free the identifier, so goto error */
853 /* Link the resource to the flow in the flow db */
854 memset(&fid_parms, 0, sizeof(fid_parms));
855 fid_parms.direction = tbl->direction;
856 fid_parms.resource_func = ident->resource_func;
857 fid_parms.resource_type = ident->ident_type;
858 fid_parms.resource_hndl = sparms.search_id;
859 fid_parms.critical_resource = tbl->critical_resource;
860 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
862 BNXT_TF_DBG(ERR, "Failed to link res to flow rc = %d\n",
864 /* Need to free the identifier, so goto error */
871 /* Need to free the identifier */
872 free_parms.dir = tbl->direction;
873 free_parms.ident_type = ident->ident_type;
874 free_parms.id = sparms.search_id;
875 (void)tf_free_identifier(tfp, &free_parms);
876 BNXT_TF_DBG(ERR, "Ident extract failed for %s:%s:%x\n",
878 tf_dir_2_str(tbl->direction), sparms.search_id);
883 ulp_mapper_field_port_db_process(struct bnxt_ulp_mapper_parms *parms,
884 struct bnxt_ulp_mapper_field_info *fld,
889 enum bnxt_ulp_port_table port_data = val16;
892 case BNXT_ULP_PORT_TABLE_DRV_FUNC_PARENT_MAC:
893 if (ulp_port_db_parent_mac_addr_get(parms->ulp_ctx, port_id,
895 BNXT_TF_DBG(ERR, "Invalid port id %u\n", port_id);
900 BNXT_TF_DBG(ERR, "Invalid port_data %s\n", fld->description);
907 ulp_mapper_field_process_inc_dec(struct bnxt_ulp_mapper_field_info *fld,
908 struct ulp_blob *blob,
910 uint16_t const_val16,
912 uint32_t *update_flag)
914 uint64_t l_val64 = *val64;
916 if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_PLUS_CONST ||
917 fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_PLUS_CONST_POST) {
918 l_val64 += const_val16;
919 l_val64 = tfp_be_to_cpu_64(l_val64);
920 ulp_blob_push_64(blob, &l_val64, bitlen);
921 } else if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_MINUS_CONST ||
922 fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_MINUS_CONST_POST) {
923 l_val64 -= const_val16;
924 l_val64 = tfp_be_to_cpu_64(l_val64);
925 ulp_blob_push_64(blob, &l_val64, bitlen);
927 BNXT_TF_DBG(ERR, "Invalid field opcode %u\n", fld->field_opc);
931 if (fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_MINUS_CONST_POST ||
932 fld->field_opc == BNXT_ULP_FIELD_OPC_SRC1_PLUS_CONST_POST) {
940 ulp_mapper_field_process(struct bnxt_ulp_mapper_parms *parms,
942 struct bnxt_ulp_mapper_field_info *fld,
943 struct ulp_blob *blob,
947 uint32_t val_size = 0, field_size = 0;
948 uint64_t hdr_bit, act_bit, regval;
949 uint16_t write_idx = blob->write_idx;
950 uint16_t idx, size_idx, bitlen, offset;
954 uint32_t src1_sel = 0;
955 enum bnxt_ulp_field_src fld_src;
956 uint8_t *fld_src_oper;
957 enum bnxt_ulp_field_cond_src field_cond_src;
958 uint16_t const_val = 0;
959 uint32_t update_flag = 0;
963 /* process the field opcode */
964 if (fld->field_opc != BNXT_ULP_FIELD_OPC_COND_OP) {
965 field_cond_src = BNXT_ULP_FIELD_COND_SRC_TRUE;
966 /* Read the constant from the second operand */
967 memcpy(&const_val, fld->field_opr2, sizeof(uint16_t));
968 const_val = tfp_be_to_cpu_16(const_val);
970 field_cond_src = fld->field_cond_src;
973 bitlen = fld->field_bit_size;
974 /* Evaluate the condition */
975 switch (field_cond_src) {
976 case BNXT_ULP_FIELD_COND_SRC_TRUE:
979 case BNXT_ULP_FIELD_COND_SRC_CF:
980 if (!ulp_operand_read(fld->field_cond_opr,
981 (uint8_t *)&idx, sizeof(uint16_t))) {
982 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
985 idx = tfp_be_to_cpu_16(idx);
986 if (idx >= BNXT_ULP_CF_IDX_LAST) {
987 BNXT_TF_DBG(ERR, "%s invalid index %u\n", name, idx);
990 /* check if the computed field is set */
991 if (ULP_COMP_FLD_IDX_RD(parms, idx))
994 case BNXT_ULP_FIELD_COND_SRC_RF:
995 if (!ulp_operand_read(fld->field_cond_opr,
996 (uint8_t *)&idx, sizeof(uint16_t))) {
997 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1001 idx = tfp_be_to_cpu_16(idx);
1002 /* Uninitialized regfile entries return 0 */
1003 if (!ulp_regfile_read(parms->regfile, idx, ®val)) {
1004 BNXT_TF_DBG(ERR, "%s regfile[%d] read oob\n",
1011 case BNXT_ULP_FIELD_COND_SRC_ACT_BIT:
1012 if (!ulp_operand_read(fld->field_cond_opr,
1013 (uint8_t *)&act_bit, sizeof(uint64_t))) {
1014 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1017 act_bit = tfp_be_to_cpu_64(act_bit);
1018 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit))
1021 case BNXT_ULP_FIELD_COND_SRC_HDR_BIT:
1022 if (!ulp_operand_read(fld->field_cond_opr,
1023 (uint8_t *)&hdr_bit, sizeof(uint64_t))) {
1024 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1027 hdr_bit = tfp_be_to_cpu_64(hdr_bit);
1028 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, hdr_bit))
1031 case BNXT_ULP_FIELD_COND_SRC_FIELD_BIT:
1032 if (!ulp_operand_read(fld->field_cond_opr, (uint8_t *)&idx,
1033 sizeof(uint16_t))) {
1034 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
1037 idx = tfp_be_to_cpu_16(idx);
1038 /* get the index from the global field list */
1039 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1040 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1044 if (bit && (ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit)))
1048 BNXT_TF_DBG(ERR, "%s invalid field opcode 0x%x at %d\n",
1049 name, fld->field_cond_src, write_idx);
1053 /* pick the selected source */
1055 fld_src = fld->field_src1;
1056 fld_src_oper = fld->field_opr1;
1058 fld_src = fld->field_src2;
1059 fld_src_oper = fld->field_opr2;
1062 /* Perform the action */
1064 case BNXT_ULP_FIELD_SRC_ZERO:
1065 if (ulp_blob_pad_push(blob, bitlen) < 0) {
1066 BNXT_TF_DBG(ERR, "%s too large for blob\n", name);
1070 case BNXT_ULP_FIELD_SRC_CONST:
1072 if (!ulp_blob_push(blob, val, bitlen)) {
1073 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1077 case BNXT_ULP_FIELD_SRC_ONES:
1078 val = mapper_fld_ones;
1079 if (!ulp_blob_push(blob, val, bitlen)) {
1080 BNXT_TF_DBG(ERR, "%s too large for blob\n", name);
1084 case BNXT_ULP_FIELD_SRC_CF:
1085 if (!ulp_operand_read(fld_src_oper,
1086 (uint8_t *)&idx, sizeof(uint16_t))) {
1087 BNXT_TF_DBG(ERR, "%s operand read failed.\n",
1091 idx = tfp_be_to_cpu_16(idx);
1092 if (idx >= BNXT_ULP_CF_IDX_LAST) {
1093 BNXT_TF_DBG(ERR, "%s comp field [%d] read oob\n",
1097 if (fld->field_opc == BNXT_ULP_FIELD_OPC_COND_OP) {
1098 val = ulp_blob_push_32(blob, &parms->comp_fld[idx],
1101 BNXT_TF_DBG(ERR, "%s push to blob failed\n",
1105 } else if (fld->field_opc == BNXT_ULP_FIELD_OPC_PORT_TABLE) {
1106 port_id = ULP_COMP_FLD_IDX_RD(parms, idx);
1107 if (ulp_mapper_field_port_db_process(parms, fld,
1110 BNXT_TF_DBG(ERR, "%s field port table failed\n",
1114 if (!ulp_blob_push(blob, val, bitlen)) {
1115 BNXT_TF_DBG(ERR, "%s push to blob failed\n",
1120 src1_val64 = ULP_COMP_FLD_IDX_RD(parms, idx);
1121 if (ulp_mapper_field_process_inc_dec(fld, blob,
1126 BNXT_TF_DBG(ERR, "%s field cond opc failed\n",
1131 BNXT_TF_DBG(ERR, "%s invalid field cond opc\n",
1137 case BNXT_ULP_FIELD_SRC_RF:
1138 if (!ulp_operand_read(fld_src_oper,
1139 (uint8_t *)&idx, sizeof(uint16_t))) {
1140 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1144 idx = tfp_be_to_cpu_16(idx);
1145 /* Uninitialized regfile entries return 0 */
1146 if (!ulp_regfile_read(parms->regfile, idx, ®val)) {
1147 BNXT_TF_DBG(ERR, "%s regfile[%d] read oob\n",
1151 if (fld->field_opc == BNXT_ULP_FIELD_OPC_COND_OP) {
1152 val = ulp_blob_push_64(blob, ®val, bitlen);
1154 BNXT_TF_DBG(ERR, "%s push to blob failed\n",
1159 if (ulp_mapper_field_process_inc_dec(fld, blob,
1164 BNXT_TF_DBG(ERR, "%s field cond opc failed\n",
1169 regval = tfp_cpu_to_be_64(regval);
1170 if (ulp_regfile_write(parms->regfile, idx,
1173 "Write regfile[%d] fail\n",
1180 case BNXT_ULP_FIELD_SRC_ACT_PROP:
1181 if (!ulp_operand_read(fld_src_oper,
1182 (uint8_t *)&idx, sizeof(uint16_t))) {
1183 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1186 idx = tfp_be_to_cpu_16(idx);
1188 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1189 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
1192 val = &parms->act_prop->act_details[idx];
1193 field_size = ulp_mapper_act_prop_size_get(idx);
1194 if (bitlen < ULP_BYTE_2_BITS(field_size)) {
1195 field_size = field_size - ((bitlen + 7) / 8);
1198 if (!ulp_blob_push(blob, val, bitlen)) {
1199 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1203 case BNXT_ULP_FIELD_SRC_ACT_PROP_SZ:
1204 if (!ulp_operand_read(fld_src_oper,
1205 (uint8_t *)&idx, sizeof(uint16_t))) {
1206 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1209 idx = tfp_be_to_cpu_16(idx);
1211 if (idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1212 BNXT_TF_DBG(ERR, "%s act_prop[%d] oob\n", name, idx);
1215 val = &parms->act_prop->act_details[idx];
1217 /* get the size index next */
1218 if (!ulp_operand_read(&fld_src_oper[sizeof(uint16_t)],
1219 (uint8_t *)&size_idx, sizeof(uint16_t))) {
1220 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1223 size_idx = tfp_be_to_cpu_16(size_idx);
1225 if (size_idx >= BNXT_ULP_ACT_PROP_IDX_LAST) {
1226 BNXT_TF_DBG(ERR, "act_prop[%d] oob\n", size_idx);
1229 memcpy(&val_size, &parms->act_prop->act_details[size_idx],
1231 val_size = tfp_be_to_cpu_32(val_size);
1232 val_size = ULP_BYTE_2_BITS(val_size);
1233 ulp_blob_push_encap(blob, val, val_size);
1235 case BNXT_ULP_FIELD_SRC_GLB_RF:
1236 if (!ulp_operand_read(fld_src_oper,
1238 sizeof(uint16_t))) {
1239 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
1242 idx = tfp_be_to_cpu_16(idx);
1243 if (ulp_mapper_glb_resource_read(parms->mapper_data,
1246 BNXT_TF_DBG(ERR, "%s global regfile[%d] read failed.\n",
1250 if (fld->field_opc == BNXT_ULP_FIELD_OPC_COND_OP) {
1251 val = ulp_blob_push_64(blob, ®val, bitlen);
1253 BNXT_TF_DBG(ERR, "%s push to blob failed\n",
1258 if (ulp_mapper_field_process_inc_dec(fld, blob,
1263 BNXT_TF_DBG(ERR, "%s field cond opc failed\n",
1268 BNXT_TF_DBG(ERR, "%s invalid field cond opc\n",
1274 case BNXT_ULP_FIELD_SRC_HF:
1275 if (!ulp_operand_read(fld_src_oper, (uint8_t *)&idx,
1276 sizeof(uint16_t))) {
1277 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
1280 idx = tfp_be_to_cpu_16(idx);
1281 /* get the index from the global field list */
1282 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1283 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1288 val = parms->hdr_field[bit].spec;
1290 val = parms->hdr_field[bit].mask;
1293 * Need to account for how much data was pushed to the header
1294 * field vs how much is to be inserted in the key/mask.
1296 field_size = parms->hdr_field[bit].size;
1297 if (bitlen < ULP_BYTE_2_BITS(field_size)) {
1298 field_size = field_size - ((bitlen + 7) / 8);
1302 if (!ulp_blob_push(blob, val, bitlen)) {
1303 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1307 case BNXT_ULP_FIELD_SRC_HDR_BIT:
1308 if (!ulp_operand_read(fld_src_oper,
1309 (uint8_t *)&hdr_bit, sizeof(uint64_t))) {
1310 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1313 hdr_bit = tfp_be_to_cpu_64(hdr_bit);
1314 memset(tmpval, 0, sizeof(tmpval));
1315 if (ULP_BITMAP_ISSET(parms->hdr_bitmap->bits, hdr_bit))
1317 if (bitlen > ULP_BYTE_2_BITS(sizeof(tmpval))) {
1318 BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name);
1321 if (!ulp_blob_push(blob, tmpval, bitlen)) {
1322 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1327 case BNXT_ULP_FIELD_SRC_ACT_BIT:
1328 if (!ulp_operand_read(fld_src_oper,
1329 (uint8_t *)&act_bit, sizeof(uint64_t))) {
1330 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1333 act_bit = tfp_be_to_cpu_64(act_bit);
1334 memset(tmpval, 0, sizeof(tmpval));
1335 if (ULP_BITMAP_ISSET(parms->act_bitmap->bits, act_bit))
1337 if (bitlen > ULP_BYTE_2_BITS(sizeof(tmpval))) {
1338 BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name);
1341 if (!ulp_blob_push(blob, tmpval, bitlen)) {
1342 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1347 case BNXT_ULP_FIELD_SRC_FIELD_BIT:
1348 if (!ulp_operand_read(fld_src_oper, (uint8_t *)&idx,
1349 sizeof(uint16_t))) {
1350 BNXT_TF_DBG(ERR, "%s operand read failed.\n", name);
1353 idx = tfp_be_to_cpu_16(idx);
1354 /* get the index from the global field list */
1355 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1356 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1360 memset(tmpval, 0, sizeof(tmpval));
1361 if (ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit))
1363 if (bitlen > ULP_BYTE_2_BITS(sizeof(tmpval))) {
1364 BNXT_TF_DBG(ERR, "%s field size is incorrect\n", name);
1367 if (!ulp_blob_push(blob, tmpval, bitlen)) {
1368 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1373 case BNXT_ULP_FIELD_SRC_SKIP:
1376 case BNXT_ULP_FIELD_SRC_REJECT:
1378 case BNXT_ULP_FIELD_SRC_SUB_HF:
1379 if (!ulp_operand_read(fld_src_oper,
1380 (uint8_t *)&idx, sizeof(uint16_t))) {
1381 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1384 idx = tfp_be_to_cpu_16(idx);
1385 /* get the index from the global field list */
1386 if (ulp_mapper_glb_field_tbl_get(parms, idx, &bit)) {
1387 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
1392 /* get the offset next */
1393 if (!ulp_operand_read(&fld_src_oper[sizeof(uint16_t)],
1394 (uint8_t *)&offset, sizeof(uint16_t))) {
1395 BNXT_TF_DBG(ERR, "%s operand read failed\n", name);
1398 offset = tfp_be_to_cpu_16(offset);
1399 if ((offset + bitlen) >
1400 ULP_BYTE_2_BITS(parms->hdr_field[bit].size) ||
1401 ULP_BITS_IS_BYTE_NOT_ALIGNED(offset)) {
1402 BNXT_TF_DBG(ERR, "Hdr field[%s] oob\n", name);
1405 offset = ULP_BITS_2_BYTE_NR(offset);
1407 /* write the value into blob */
1409 val = &parms->hdr_field[bit].spec[offset];
1411 val = &parms->hdr_field[bit].mask[offset];
1413 if (!ulp_blob_push(blob, val, bitlen)) {
1414 BNXT_TF_DBG(ERR, "%s push to blob failed\n", name);
1419 BNXT_TF_DBG(ERR, "%s invalid field opcode 0x%x at %d\n",
1420 name, fld_src, write_idx);
1427 * Result table process and fill the result blob.
1428 * data [out] - the result blob data
1431 ulp_mapper_tbl_result_build(struct bnxt_ulp_mapper_parms *parms,
1432 struct bnxt_ulp_mapper_tbl_info *tbl,
1433 struct ulp_blob *data,
1436 struct bnxt_ulp_mapper_field_info *dflds;
1437 uint32_t i, num_flds = 0, encap_flds = 0;
1440 /* Get the result field list */
1441 dflds = ulp_mapper_result_fields_get(parms, tbl, &num_flds,
1444 /* validate the result field list counts */
1445 if ((tbl->resource_func == BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1446 (!num_flds && !encap_flds)) || !dflds ||
1447 (tbl->resource_func != BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE &&
1448 (!num_flds || encap_flds))) {
1449 BNXT_TF_DBG(ERR, "Failed to get data fields %x:%x\n",
1450 num_flds, encap_flds);
1454 /* process the result fields, loop through them */
1455 for (i = 0; i < (num_flds + encap_flds); i++) {
1456 /* set the swap index if encap swap bit is enabled */
1457 if (parms->device_params->encap_byte_swap && encap_flds &&
1459 ulp_blob_encap_swap_idx_set(data);
1461 /* Process the result fields */
1462 rc = ulp_mapper_field_process(parms, tbl->direction,
1463 &dflds[i], data, 0, name);
1465 BNXT_TF_DBG(ERR, "data field failed\n");
1470 /* if encap bit swap is enabled perform the bit swap */
1471 if (parms->device_params->encap_byte_swap && encap_flds)
1472 ulp_blob_perform_encap_swap(data);
1478 ulp_mapper_mark_gfid_process(struct bnxt_ulp_mapper_parms *parms,
1479 struct bnxt_ulp_mapper_tbl_info *tbl,
1482 struct ulp_flow_db_res_params fid_parms;
1483 uint32_t mark, gfid, mark_flag;
1484 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1487 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1488 !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1489 ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1490 BNXT_ULP_ACT_BIT_MARK)))
1491 return rc; /* no need to perform gfid process */
1493 /* Get the mark id details from action property */
1494 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1496 mark = tfp_be_to_cpu_32(mark);
1498 TF_GET_GFID_FROM_FLOW_ID(flow_id, gfid);
1499 mark_flag = BNXT_ULP_MARK_GLOBAL_HW_FID;
1501 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1504 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1507 fid_parms.direction = tbl->direction;
1508 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1509 fid_parms.critical_resource = tbl->critical_resource;
1510 fid_parms.resource_type = mark_flag;
1511 fid_parms.resource_hndl = gfid;
1512 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1514 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1519 ulp_mapper_mark_act_ptr_process(struct bnxt_ulp_mapper_parms *parms,
1520 struct bnxt_ulp_mapper_tbl_info *tbl)
1522 struct ulp_flow_db_res_params fid_parms;
1523 uint32_t act_idx, mark, mark_flag;
1525 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1528 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1529 !(mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION &&
1530 ULP_BITMAP_ISSET(parms->act_bitmap->bits,
1531 BNXT_ULP_ACT_BIT_MARK)))
1532 return rc; /* no need to perform mark action process */
1534 /* Get the mark id details from action property */
1535 memcpy(&mark, &parms->act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_MARK],
1537 mark = tfp_be_to_cpu_32(mark);
1539 if (!ulp_regfile_read(parms->regfile,
1540 BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1542 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1545 act_idx = tfp_be_to_cpu_64(val64);
1546 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID;
1547 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1550 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1553 fid_parms.direction = tbl->direction;
1554 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1555 fid_parms.critical_resource = tbl->critical_resource;
1556 fid_parms.resource_type = mark_flag;
1557 fid_parms.resource_hndl = act_idx;
1558 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1560 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1565 ulp_mapper_mark_vfr_idx_process(struct bnxt_ulp_mapper_parms *parms,
1566 struct bnxt_ulp_mapper_tbl_info *tbl)
1568 struct ulp_flow_db_res_params fid_parms;
1569 uint32_t act_idx, mark, mark_flag;
1571 enum bnxt_ulp_mark_db_opc mark_op = tbl->mark_db_opcode;
1574 if (mark_op == BNXT_ULP_MARK_DB_OPC_NOP ||
1575 mark_op == BNXT_ULP_MARK_DB_OPC_PUSH_IF_MARK_ACTION)
1576 return rc; /* no need to perform mark action process */
1578 /* Get the mark id details from the computed field of dev port id */
1579 mark = ULP_COMP_FLD_IDX_RD(parms, BNXT_ULP_CF_IDX_DEV_PORT_ID);
1581 /* Get the main action pointer */
1582 if (!ulp_regfile_read(parms->regfile,
1583 BNXT_ULP_RF_IDX_MAIN_ACTION_PTR,
1585 BNXT_TF_DBG(ERR, "read action ptr main failed\n");
1588 act_idx = tfp_be_to_cpu_64(val64);
1590 /* Set the mark flag to local fid and vfr flag */
1591 mark_flag = BNXT_ULP_MARK_LOCAL_HW_FID | BNXT_ULP_MARK_VFR_ID;
1593 rc = ulp_mark_db_mark_add(parms->ulp_ctx, mark_flag,
1596 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
1599 fid_parms.direction = tbl->direction;
1600 fid_parms.resource_func = BNXT_ULP_RESOURCE_FUNC_HW_FID;
1601 fid_parms.critical_resource = tbl->critical_resource;
1602 fid_parms.resource_type = mark_flag;
1603 fid_parms.resource_hndl = act_idx;
1604 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1606 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n", rc);
1610 /* Tcam table scan the identifier list and allocate each identifier */
1612 ulp_mapper_tcam_tbl_scan_ident_alloc(struct bnxt_ulp_mapper_parms *parms,
1613 struct bnxt_ulp_mapper_tbl_info *tbl)
1615 struct bnxt_ulp_mapper_ident_info *idents;
1616 uint32_t num_idents;
1619 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1620 for (i = 0; i < num_idents; i++) {
1621 if (ulp_mapper_ident_process(parms, tbl,
1629 * Tcam table scan the identifier list and extract the identifier from
1633 ulp_mapper_tcam_tbl_scan_ident_extract(struct bnxt_ulp_mapper_parms *parms,
1634 struct bnxt_ulp_mapper_tbl_info *tbl,
1635 struct ulp_blob *data)
1637 struct bnxt_ulp_mapper_ident_info *idents;
1638 uint32_t num_idents = 0, i;
1642 * Extract the listed identifiers from the result field,
1643 * no need to allocate them.
1645 idents = ulp_mapper_ident_fields_get(parms, tbl, &num_idents);
1646 for (i = 0; i < num_idents; i++) {
1647 rc = ulp_mapper_ident_extract(parms, tbl, &idents[i], data);
1649 BNXT_TF_DBG(ERR, "Error in identifier extraction\n");
1656 /* Internal function to write the tcam entry */
1658 ulp_mapper_tcam_tbl_entry_write(struct bnxt_ulp_mapper_parms *parms,
1659 struct bnxt_ulp_mapper_tbl_info *tbl,
1660 struct ulp_blob *key,
1661 struct ulp_blob *mask,
1662 struct ulp_blob *data,
1665 struct tf_set_tcam_entry_parms sparms = { 0 };
1670 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1672 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1676 sparms.dir = tbl->direction;
1677 sparms.tcam_tbl_type = tbl->resource_type;
1679 /* Already verified the key/mask lengths */
1680 sparms.key = ulp_blob_data_get(key, &tmplen);
1681 sparms.mask = ulp_blob_data_get(mask, &tmplen);
1682 sparms.key_sz_in_bits = tbl->key_bit_size;
1683 sparms.result = ulp_blob_data_get(data, &tmplen);
1685 if (tbl->result_bit_size != tmplen) {
1686 BNXT_TF_DBG(ERR, "Result len (%d) != Expected (%d)\n",
1687 tmplen, tbl->result_bit_size);
1690 sparms.result_sz_in_bits = tbl->result_bit_size;
1691 if (tf_set_tcam_entry(tfp, &sparms)) {
1692 BNXT_TF_DBG(ERR, "tcam[%s][%s][%x] write failed.\n",
1693 tf_tcam_tbl_2_str(sparms.tcam_tbl_type),
1694 tf_dir_2_str(sparms.dir), sparms.idx);
1699 rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
1701 BNXT_TF_DBG(ERR, "failed mark action processing\n");
1708 /* internal function to post process the key/mask blobs for wildcard tcam tbl */
1709 static void ulp_mapper_wc_tcam_tbl_post_process(struct ulp_blob *blob)
1711 ulp_blob_perform_64B_word_swap(blob);
1712 ulp_blob_perform_64B_byte_swap(blob);
1716 ulp_mapper_tcam_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1717 struct bnxt_ulp_mapper_tbl_info *tbl)
1719 struct bnxt_ulp_mapper_key_info *kflds;
1720 struct ulp_blob key, mask, data, update_data;
1721 uint32_t i, num_kflds;
1724 struct tf_alloc_tcam_entry_parms aparms = { 0 };
1725 struct tf_search_tcam_entry_parms searchparms = { 0 };
1726 struct ulp_flow_db_res_params fid_parms = { 0 };
1727 struct tf_free_tcam_entry_parms free_parms = { 0 };
1729 uint16_t tmplen = 0;
1732 /* Skip this if table opcode is NOP */
1733 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_NOT_USED ||
1734 tbl->tbl_opcode >= BNXT_ULP_TCAM_TBL_OPC_LAST) {
1735 BNXT_TF_DBG(ERR, "Invalid tcam table opcode %d\n",
1740 tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1742 BNXT_TF_DBG(ERR, "Failed to get truflow pointer\n");
1746 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
1747 if (!kflds || !num_kflds) {
1748 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1752 if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
1753 parms->device_params->byte_order) ||
1754 !ulp_blob_init(&mask, tbl->blob_key_bit_size,
1755 parms->device_params->byte_order) ||
1756 !ulp_blob_init(&data, tbl->result_bit_size,
1757 parms->device_params->byte_order) ||
1758 !ulp_blob_init(&update_data, tbl->result_bit_size,
1759 parms->device_params->byte_order)) {
1760 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1764 if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM) {
1765 key.byte_order = BNXT_ULP_BYTE_ORDER_BE;
1766 mask.byte_order = BNXT_ULP_BYTE_ORDER_BE;
1769 /* create the key/mask */
1771 * NOTE: The WC table will require some kind of flag to handle the
1772 * mode bits within the key/mask
1774 for (i = 0; i < num_kflds; i++) {
1776 rc = ulp_mapper_field_process(parms, tbl->direction,
1777 &kflds[i].field_info_spec,
1778 &key, 1, "TCAM Key");
1780 BNXT_TF_DBG(ERR, "Key field set failed %s\n",
1781 kflds[i].field_info_spec.description);
1785 /* Setup the mask */
1786 rc = ulp_mapper_field_process(parms, tbl->direction,
1787 &kflds[i].field_info_mask,
1788 &mask, 0, "TCAM Mask");
1790 BNXT_TF_DBG(ERR, "Mask field set failed %s\n",
1791 kflds[i].field_info_mask.description);
1796 /* For wild card tcam perform the post process to swap the blob */
1797 if (tbl->resource_type == TF_TCAM_TBL_TYPE_WC_TCAM) {
1798 ulp_mapper_wc_tcam_tbl_post_process(&key);
1799 ulp_mapper_wc_tcam_tbl_post_process(&mask);
1802 if (tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
1803 /* allocate the tcam index */
1804 aparms.dir = tbl->direction;
1805 aparms.tcam_tbl_type = tbl->resource_type;
1806 aparms.key = ulp_blob_data_get(&key, &tmplen);
1807 aparms.key_sz_in_bits = tmplen;
1808 if (tbl->blob_key_bit_size != tmplen) {
1809 BNXT_TF_DBG(ERR, "Key len (%d) != Expected (%d)\n",
1810 tmplen, tbl->blob_key_bit_size);
1814 aparms.mask = ulp_blob_data_get(&mask, &tmplen);
1815 if (tbl->blob_key_bit_size != tmplen) {
1816 BNXT_TF_DBG(ERR, "Mask len (%d) != Expected (%d)\n",
1817 tmplen, tbl->blob_key_bit_size);
1821 /* calculate the entry priority */
1822 rc = ulp_mapper_priority_opc_process(parms, tbl,
1825 BNXT_TF_DBG(ERR, "entry priority process failed\n");
1829 rc = tf_alloc_tcam_entry(tfp, &aparms);
1831 BNXT_TF_DBG(ERR, "tcam alloc failed rc=%d.\n", rc);
1838 * Searching before allocation to see if we already have an
1839 * entry. This allows re-use of a constrained resource.
1841 searchparms.dir = tbl->direction;
1842 searchparms.tcam_tbl_type = tbl->resource_type;
1843 searchparms.key = ulp_blob_data_get(&key, &tmplen);
1844 searchparms.key_sz_in_bits = tbl->key_bit_size;
1845 searchparms.mask = ulp_blob_data_get(&mask, &tmplen);
1846 searchparms.alloc = 1;
1847 searchparms.result = ulp_blob_data_get(&data, &tmplen);
1848 searchparms.result_sz_in_bits = tbl->result_bit_size;
1850 /* calculate the entry priority */
1851 rc = ulp_mapper_priority_opc_process(parms, tbl,
1852 &searchparms.priority);
1854 BNXT_TF_DBG(ERR, "entry priority process failed\n");
1858 rc = tf_search_tcam_entry(tfp, &searchparms);
1860 BNXT_TF_DBG(ERR, "tcam search failed rc=%d\n", rc);
1864 /* Successful search, check the result */
1865 if (searchparms.search_status == REJECT) {
1866 BNXT_TF_DBG(ERR, "tcam alloc rejected\n");
1869 idx = searchparms.idx;
1870 hit = searchparms.hit;
1873 /* Write the tcam index into the regfile*/
1874 if (ulp_regfile_write(parms->regfile, tbl->tbl_operand,
1875 (uint64_t)tfp_cpu_to_be_64(idx))) {
1876 BNXT_TF_DBG(ERR, "Regfile[%d] write failed.\n",
1879 /* Need to free the tcam idx, so goto error */
1883 /* if it is miss then it is same as no search before alloc */
1884 if (!hit || tbl->tbl_opcode == BNXT_ULP_TCAM_TBL_OPC_ALLOC_WR_REGFILE) {
1885 /*Scan identifier list, allocate identifier and update regfile*/
1886 rc = ulp_mapper_tcam_tbl_scan_ident_alloc(parms, tbl);
1887 /* Create the result blob */
1889 rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
1891 /* write the tcam entry */
1893 rc = ulp_mapper_tcam_tbl_entry_write(parms, tbl, &key,
1896 /*Scan identifier list, extract identifier and update regfile*/
1897 rc = ulp_mapper_tcam_tbl_scan_ident_extract(parms, tbl, &data);
1902 /* Add the tcam index to the flow database */
1903 fid_parms.direction = tbl->direction;
1904 fid_parms.resource_func = tbl->resource_func;
1905 fid_parms.resource_type = tbl->resource_type;
1906 fid_parms.critical_resource = tbl->critical_resource;
1907 fid_parms.resource_hndl = idx;
1908 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
1910 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
1912 /* Need to free the identifier, so goto error */
1918 free_parms.dir = tbl->direction;
1919 free_parms.tcam_tbl_type = tbl->resource_type;
1920 free_parms.idx = idx;
1921 trc = tf_free_tcam_entry(tfp, &free_parms);
1923 BNXT_TF_DBG(ERR, "Failed to free tcam[%d][%d][%d] on failure\n",
1924 tbl->resource_type, tbl->direction, idx);
1929 ulp_mapper_em_tbl_process(struct bnxt_ulp_mapper_parms *parms,
1930 struct bnxt_ulp_mapper_tbl_info *tbl)
1932 struct bnxt_ulp_mapper_key_info *kflds;
1933 struct ulp_blob key, data;
1934 uint32_t i, num_kflds;
1936 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
1937 struct ulp_flow_db_res_params fid_parms = { 0 };
1938 struct tf_insert_em_entry_parms iparms = { 0 };
1939 struct tf_delete_em_entry_parms free_parms = { 0 };
1940 enum bnxt_ulp_flow_mem_type mtype;
1944 rc = bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype);
1946 BNXT_TF_DBG(ERR, "Failed to get the mem type for EM\n");
1950 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
1951 if (!kflds || !num_kflds) {
1952 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
1956 /* Initialize the key/result blobs */
1957 if (!ulp_blob_init(&key, tbl->blob_key_bit_size,
1958 parms->device_params->byte_order) ||
1959 !ulp_blob_init(&data, tbl->result_bit_size,
1960 parms->device_params->byte_order)) {
1961 BNXT_TF_DBG(ERR, "blob inits failed.\n");
1965 /* create the key */
1966 for (i = 0; i < num_kflds; i++) {
1968 rc = ulp_mapper_field_process(parms, tbl->direction,
1969 &kflds[i].field_info_spec,
1972 BNXT_TF_DBG(ERR, "Key field set failed.\n");
1978 * TBD: Normally should process identifiers in case of using recycle or
1979 * loopback. Not supporting recycle for now.
1982 /* Create the result data blob */
1983 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "EM Result");
1985 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
1988 /* do the transpose for the internal EM keys */
1989 if (tbl->resource_type == TF_MEM_INTERNAL)
1990 ulp_blob_perform_byte_reverse(&key);
1992 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx,
1993 &iparms.tbl_scope_id);
1995 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
2000 * NOTE: the actual blob size will differ from the size in the tbl
2001 * entry due to the padding.
2003 iparms.dup_check = 0;
2004 iparms.dir = tbl->direction;
2005 iparms.mem = tbl->resource_type;
2006 iparms.key = ulp_blob_data_get(&key, &tmplen);
2007 iparms.key_sz_in_bits = tbl->key_bit_size;
2008 iparms.em_record = ulp_blob_data_get(&data, &tmplen);
2009 iparms.em_record_sz_in_bits = tbl->result_bit_size;
2011 rc = tf_insert_em_entry(tfp, &iparms);
2013 BNXT_TF_DBG(ERR, "Failed to insert em entry rc=%d.\n", rc);
2017 /* Mark action process */
2018 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT &&
2019 tbl->resource_type == TF_MEM_EXTERNAL)
2020 rc = ulp_mapper_mark_gfid_process(parms, tbl, iparms.flow_id);
2021 else if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT &&
2022 tbl->resource_type == TF_MEM_INTERNAL)
2023 rc = ulp_mapper_mark_act_ptr_process(parms, tbl);
2025 BNXT_TF_DBG(ERR, "Failed to add mark to flow\n");
2029 /* Link the EM resource to the flow in the flow db */
2030 memset(&fid_parms, 0, sizeof(fid_parms));
2031 fid_parms.direction = tbl->direction;
2032 fid_parms.resource_func = tbl->resource_func;
2033 fid_parms.resource_type = tbl->resource_type;
2034 fid_parms.critical_resource = tbl->critical_resource;
2035 fid_parms.resource_hndl = iparms.flow_handle;
2037 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2039 BNXT_TF_DBG(ERR, "Fail to link res to flow rc = %d\n",
2041 /* Need to free the identifier, so goto error */
2047 free_parms.dir = iparms.dir;
2048 free_parms.mem = iparms.mem;
2049 free_parms.tbl_scope_id = iparms.tbl_scope_id;
2050 free_parms.flow_handle = iparms.flow_handle;
2052 trc = tf_delete_em_entry(tfp, &free_parms);
2054 BNXT_TF_DBG(ERR, "Failed to delete EM entry on failed add\n");
2060 ulp_mapper_index_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2061 struct bnxt_ulp_mapper_tbl_info *tbl)
2063 struct ulp_flow_db_res_params fid_parms;
2064 struct ulp_blob data;
2065 uint64_t regval = 0;
2067 uint32_t index, hit;
2068 int32_t rc = 0, trc = 0;
2069 struct tf_alloc_tbl_entry_parms aparms = { 0 };
2070 struct tf_search_tbl_entry_parms srchparms = { 0 };
2071 struct tf_set_tbl_entry_parms sparms = { 0 };
2072 struct tf_get_tbl_entry_parms gparms = { 0 };
2073 struct tf_free_tbl_entry_parms free_parms = { 0 };
2074 uint32_t tbl_scope_id;
2075 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
2079 bool search = false;
2080 uint64_t act_rec_size;
2082 /* use the max size if encap is enabled */
2083 if (tbl->encap_num_fields)
2084 bit_size = BNXT_ULP_FLMP_BLOB_SIZE_IN_BITS;
2086 bit_size = tbl->result_bit_size;
2088 /* Initialize the blob data */
2089 if (!ulp_blob_init(&data, bit_size,
2090 parms->device_params->byte_order)) {
2091 BNXT_TF_DBG(ERR, "Failed to initialize index table blob\n");
2095 /* Get the scope id first */
2096 rc = bnxt_ulp_cntxt_tbl_scope_id_get(parms->ulp_ctx, &tbl_scope_id);
2098 BNXT_TF_DBG(ERR, "Failed to get table scope rc=%d\n", rc);
2102 switch (tbl->tbl_opcode) {
2103 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_REGFILE:
2106 case BNXT_ULP_INDEX_TBL_OPC_ALLOC_WR_REGFILE:
2108 * Build the entry, alloc an index, write the table, and store
2109 * the data in the regfile.
2114 case BNXT_ULP_INDEX_TBL_OPC_SRCH_ALLOC_WR_REGFILE:
2115 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2116 /* Not currently supporting with EXT */
2118 "Ext Table Search Opcode not supported.\n");
2122 * Search for the entry in the tf core. If it is hit, save the
2123 * index in the regfile. If it is a miss, Build the entry,
2124 * alloc an index, write the table, and store the data in the
2125 * regfile (same as ALLOC_WR).
2129 case BNXT_ULP_INDEX_TBL_OPC_WR_REGFILE:
2131 * get the index to write to from the regfile and then write
2134 if (!ulp_regfile_read(parms->regfile,
2138 "Failed to get tbl idx from regfile[%d].\n",
2142 index = tfp_be_to_cpu_64(regval);
2143 /* For external, we need to reverse shift */
2144 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2145 index = TF_ACT_REC_PTR_2_OFFSET(index);
2149 case BNXT_ULP_INDEX_TBL_OPC_WR_GLB_REGFILE:
2150 if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) {
2151 BNXT_TF_DBG(ERR, "Template error, wrong fdb opcode\n");
2155 * get the index to write to from the global regfile and then
2158 if (ulp_mapper_glb_resource_read(parms->mapper_data,
2163 "Failed to get tbl idx from Global "
2168 index = tfp_be_to_cpu_64(regval);
2169 /* For external, we need to reverse shift */
2170 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2171 index = TF_ACT_REC_PTR_2_OFFSET(index);
2174 case BNXT_ULP_INDEX_TBL_OPC_RD_REGFILE:
2176 * The read is different from the rest and can be handled here
2177 * instead of trying to use common code. Simply read the table
2178 * with the index from the regfile, scan and store the
2179 * identifiers, and return.
2181 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2182 /* Not currently supporting with EXT */
2184 "Ext Table Read Opcode not supported.\n");
2187 if (!ulp_regfile_read(parms->regfile,
2188 tbl->tbl_operand, ®val)) {
2190 "Failed to get tbl idx from regfile[%d]\n",
2194 index = tfp_be_to_cpu_64(regval);
2195 gparms.dir = tbl->direction;
2196 gparms.type = tbl->resource_type;
2197 gparms.data = ulp_blob_data_get(&data, &tmplen);
2198 gparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tbl->result_bit_size);
2200 rc = tf_get_tbl_entry(tfp, &gparms);
2202 BNXT_TF_DBG(ERR, "Failed to read the tbl entry %d:%d\n",
2203 tbl->resource_type, index);
2207 * Scan the fields in the entry and push them into the regfile.
2209 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2211 gparms.data_sz_in_bytes,
2214 BNXT_TF_DBG(ERR, "Failed to read fields on tbl read "
2220 BNXT_TF_DBG(ERR, "Invalid index table opcode %d\n",
2225 if (write || search) {
2226 /* Get the result fields list */
2227 rc = ulp_mapper_tbl_result_build(parms,
2232 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2238 /* Use the result blob to perform a search */
2239 memset(&srchparms, 0, sizeof(srchparms));
2240 srchparms.dir = tbl->direction;
2241 srchparms.type = tbl->resource_type;
2242 srchparms.alloc = 1;
2243 srchparms.result = ulp_blob_data_get(&data, &tmplen);
2244 srchparms.result_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2245 srchparms.tbl_scope_id = tbl_scope_id;
2246 rc = tf_search_tbl_entry(tfp, &srchparms);
2248 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2249 tf_tbl_type_2_str(tbl->resource_type),
2250 tf_dir_2_str(tbl->direction), rc);
2253 if (srchparms.search_status == REJECT) {
2254 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] rejected.\n",
2255 tf_tbl_type_2_str(tbl->resource_type),
2256 tf_dir_2_str(tbl->direction));
2259 index = srchparms.idx;
2260 hit = srchparms.hit;
2268 aparms.dir = tbl->direction;
2269 aparms.type = tbl->resource_type;
2270 aparms.tbl_scope_id = tbl_scope_id;
2272 /* All failures after the alloc succeeds require a free */
2273 rc = tf_alloc_tbl_entry(tfp, &aparms);
2275 BNXT_TF_DBG(ERR, "Alloc table[%s][%s] failed rc=%d\n",
2276 tf_tbl_type_2_str(tbl->resource_type),
2277 tf_dir_2_str(tbl->direction), rc);
2283 if (search || alloc) {
2285 * Store the index in the regfile since we either allocated it
2288 * Calculate the idx for the result record, for external EM the
2289 * offset needs to be shifted accordingly.
2290 * If external non-inline table types are used then need to
2291 * revisit this logic.
2293 if (tbl->resource_type == TF_TBL_TYPE_EXT)
2294 regval = TF_ACT_REC_OFFSET_2_PTR(index);
2298 rc = ulp_regfile_write(parms->regfile,
2300 tfp_cpu_to_be_64(regval));
2302 BNXT_TF_DBG(ERR, "Failed to write regfile[%d] rc=%d\n",
2303 tbl->tbl_operand, rc);
2309 sparms.dir = tbl->direction;
2310 sparms.type = tbl->resource_type;
2311 sparms.data = ulp_blob_data_get(&data, &tmplen);
2312 sparms.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2314 sparms.tbl_scope_id = tbl_scope_id;
2315 rc = tf_set_tbl_entry(tfp, &sparms);
2318 "Index table[%s][%s][%x] write failed "
2320 tf_tbl_type_2_str(sparms.type),
2321 tf_dir_2_str(sparms.dir),
2326 /* Calculate action record size */
2327 if (tbl->resource_type == TF_TBL_TYPE_EXT) {
2328 act_rec_size = (ULP_BITS_2_BYTE_NR(tmplen) + 15) / 16;
2330 if (ulp_regfile_write(parms->regfile,
2331 BNXT_ULP_RF_IDX_ACTION_REC_SIZE,
2332 tfp_cpu_to_be_64(act_rec_size)))
2334 "Failed write the act rec size\n");
2338 /* Link the resource to the flow in the flow db */
2339 memset(&fid_parms, 0, sizeof(fid_parms));
2340 fid_parms.direction = tbl->direction;
2341 fid_parms.resource_func = tbl->resource_func;
2342 fid_parms.resource_type = tbl->resource_type;
2343 fid_parms.resource_sub_type = tbl->resource_sub_type;
2344 fid_parms.resource_hndl = index;
2345 fid_parms.critical_resource = tbl->critical_resource;
2347 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2349 BNXT_TF_DBG(ERR, "Failed to link resource to flow rc = %d\n",
2354 /* Perform the VF rep action */
2355 rc = ulp_mapper_mark_vfr_idx_process(parms, tbl);
2357 BNXT_TF_DBG(ERR, "Failed to add vfr mark rc = %d\n", rc);
2363 * Free the allocated resource since we failed to either
2364 * write to the entry or link the flow
2366 free_parms.dir = tbl->direction;
2367 free_parms.type = tbl->resource_type;
2368 free_parms.idx = index;
2369 free_parms.tbl_scope_id = tbl_scope_id;
2371 trc = tf_free_tbl_entry(tfp, &free_parms);
2373 BNXT_TF_DBG(ERR, "Failed to free tbl entry on failure\n");
2379 ulp_mapper_if_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2380 struct bnxt_ulp_mapper_tbl_info *tbl)
2382 struct ulp_blob data, res_blob;
2386 struct tf_set_if_tbl_entry_parms iftbl_params = { 0 };
2387 struct tf_get_if_tbl_entry_parms get_parms = { 0 };
2388 struct tf *tfp = bnxt_ulp_cntxt_tfp_get(parms->ulp_ctx);
2389 enum bnxt_ulp_if_tbl_opc if_opc = tbl->tbl_opcode;
2392 /* Initialize the blob data */
2393 if (!ulp_blob_init(&data, tbl->result_bit_size,
2394 parms->device_params->byte_order)) {
2395 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2399 /* create the result blob */
2400 rc = ulp_mapper_tbl_result_build(parms, tbl, &data, "IFtable Result");
2402 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2406 /* Get the index details */
2408 case BNXT_ULP_IF_TBL_OPC_WR_COMP_FIELD:
2409 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2411 case BNXT_ULP_IF_TBL_OPC_WR_REGFILE:
2412 if (!ulp_regfile_read(parms->regfile, tbl->tbl_operand, &idx)) {
2413 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2417 idx = tfp_be_to_cpu_64(idx);
2419 case BNXT_ULP_IF_TBL_OPC_WR_CONST:
2420 idx = tbl->tbl_operand;
2422 case BNXT_ULP_IF_TBL_OPC_RD_COMP_FIELD:
2423 /* Initialize the result blob */
2424 if (!ulp_blob_init(&res_blob, tbl->result_bit_size,
2425 parms->device_params->byte_order)) {
2426 BNXT_TF_DBG(ERR, "Failed initial result blob\n");
2430 /* read the interface table */
2431 idx = ULP_COMP_FLD_IDX_RD(parms, tbl->tbl_operand);
2432 res_size = ULP_BITS_2_BYTE(tbl->result_bit_size);
2433 get_parms.dir = tbl->direction;
2434 get_parms.type = tbl->resource_type;
2435 get_parms.idx = idx;
2436 get_parms.data = ulp_blob_data_get(&res_blob, &tmplen);
2437 get_parms.data_sz_in_bytes = res_size;
2439 rc = tf_get_if_tbl_entry(tfp, &get_parms);
2441 BNXT_TF_DBG(ERR, "Get table[%d][%s][%x] failed rc=%d\n",
2443 tf_dir_2_str(get_parms.dir),
2447 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2450 res_blob.byte_order);
2452 BNXT_TF_DBG(ERR, "Scan and extract failed rc=%d\n", rc);
2454 case BNXT_ULP_IF_TBL_OPC_NOT_USED:
2455 return rc; /* skip it */
2457 BNXT_TF_DBG(ERR, "Invalid tbl index opcode\n");
2461 /* Perform the tf table set by filling the set params */
2462 iftbl_params.dir = tbl->direction;
2463 iftbl_params.type = tbl->resource_type;
2464 iftbl_params.data = ulp_blob_data_get(&data, &tmplen);
2465 iftbl_params.data_sz_in_bytes = ULP_BITS_2_BYTE(tmplen);
2466 iftbl_params.idx = idx;
2468 rc = tf_set_if_tbl_entry(tfp, &iftbl_params);
2470 BNXT_TF_DBG(ERR, "Set table[%d][%s][%x] failed rc=%d\n",
2471 iftbl_params.type,/* TBD: add tf_if_tbl_2_str */
2472 tf_dir_2_str(iftbl_params.dir),
2473 iftbl_params.idx, rc);
2478 * TBD: Need to look at the need to store idx in flow db for restore
2479 * the table to its original state on deletion of this entry.
2485 ulp_mapper_gen_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2486 struct bnxt_ulp_mapper_tbl_info *tbl)
2488 struct ulp_mapper_gen_tbl_list *gen_tbl_list;
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;
2492 struct ulp_gen_hash_entry_params hash_entry;
2494 struct ulp_blob key, data;
2497 uint32_t i, num_kflds = 0, key_index = 0;
2498 uint32_t gen_tbl_miss = 1, fdb_write = 0;
2502 /* Get the key fields list and build the key. */
2503 kflds = ulp_mapper_key_fields_get(parms, tbl, &num_kflds);
2504 if (!kflds || !num_kflds) {
2505 BNXT_TF_DBG(ERR, "Failed to get key fields\n");
2509 if (!ulp_blob_init(&key, tbl->key_bit_size,
2510 parms->device_params->byte_order)) {
2511 BNXT_TF_DBG(ERR, "Failed to alloc blob\n");
2514 for (i = 0; i < num_kflds; i++) {
2516 rc = ulp_mapper_field_process(parms, tbl->direction,
2517 &kflds[i].field_info_spec,
2518 &key, 1, "Gen Tbl Key");
2521 "Failed to create key for Gen tbl rc=%d\n",
2527 /* Calculate the table index for the generic table*/
2528 tbl_idx = ulp_mapper_gen_tbl_idx_calculate(tbl->resource_sub_type,
2531 BNXT_TF_DBG(ERR, "Invalid table index %x:%x\n",
2532 tbl->resource_sub_type, tbl->direction);
2536 /* The_key is a byte array convert it to a search index */
2537 cache_key = ulp_blob_data_get(&key, &tmplen);
2538 /* get the generic table */
2539 gen_tbl_list = &parms->mapper_data->gen_tbl_list[tbl_idx];
2541 /* Check if generic hash table */
2542 if (gen_tbl_list->hash_tbl) {
2543 if (tbl->gen_tbl_lkup_type !=
2544 BNXT_ULP_GENERIC_TBL_LKUP_TYPE_HASH) {
2545 BNXT_TF_DBG(ERR, "%s: Invalid template lkup type\n",
2546 gen_tbl_list->gen_tbl_name);
2549 hash_entry.key_data = cache_key;
2550 hash_entry.key_length = ULP_BITS_2_BYTE(tmplen);
2551 rc = ulp_gen_hash_tbl_list_key_search(gen_tbl_list->hash_tbl,
2554 BNXT_TF_DBG(ERR, "%s: hash tbl search failed\n",
2555 gen_tbl_list->gen_tbl_name);
2558 if (hash_entry.search_flag == ULP_GEN_HASH_SEARCH_FOUND) {
2559 key_index = hash_entry.key_idx;
2560 /* Get the generic table entry */
2561 if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list,
2565 /* store the hash index in the fdb */
2566 key_index = hash_entry.hash_index;
2569 /* convert key to index directly */
2570 memcpy(&key_index, cache_key, ULP_BITS_2_BYTE(tmplen));
2571 /* Get the generic table entry */
2572 if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list, key_index,
2576 switch (tbl->tbl_opcode) {
2577 case BNXT_ULP_GENERIC_TBL_OPC_READ:
2578 if (gen_tbl_list->hash_tbl) {
2579 if (hash_entry.search_flag != ULP_GEN_HASH_SEARCH_FOUND)
2580 break; /* nothing to be done , no entry */
2583 /* check the reference count */
2584 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2586 /* Scan ident list and create the result blob*/
2587 rc = ulp_mapper_tbl_ident_scan_ext(parms, tbl,
2593 "Failed to scan ident list\n");
2596 if (tbl->fdb_opcode != BNXT_ULP_FDB_OPC_NOP) {
2597 /* increment the reference count */
2598 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2606 case BNXT_ULP_GENERIC_TBL_OPC_WRITE:
2607 if (gen_tbl_list->hash_tbl) {
2608 rc = ulp_mapper_gen_tbl_hash_entry_add(gen_tbl_list,
2613 /* store the hash index in the fdb */
2614 key_index = hash_entry.hash_index;
2616 /* check the reference count */
2617 if (ULP_GEN_TBL_REF_CNT(&gen_tbl_ent)) {
2618 /* a hit then error */
2619 BNXT_TF_DBG(ERR, "generic entry already present\n");
2620 return -EINVAL; /* success */
2623 /* Initialize the blob data */
2624 if (!ulp_blob_init(&data, tbl->result_bit_size,
2625 gen_tbl_ent.byte_order)) {
2626 BNXT_TF_DBG(ERR, "Failed initial index table blob\n");
2630 /* Get the result fields list */
2631 rc = ulp_mapper_tbl_result_build(parms, tbl, &data,
2634 BNXT_TF_DBG(ERR, "Failed to build the result blob\n");
2637 byte_data = ulp_blob_data_get(&data, &tmplen);
2638 rc = ulp_mapper_gen_tbl_entry_data_set(&gen_tbl_ent,
2640 ULP_BITS_2_BYTE(tmplen));
2642 BNXT_TF_DBG(ERR, "Failed to write generic table\n");
2646 /* increment the reference count */
2647 ULP_GEN_TBL_REF_CNT_INC(&gen_tbl_ent);
2649 parms->shared_hndl = (uint64_t)tbl_idx << 32 | key_index;
2652 BNXT_TF_DBG(ERR, "Invalid table opcode %x\n", tbl->tbl_opcode);
2656 /* Set the generic entry hit */
2657 rc = ulp_regfile_write(parms->regfile,
2658 BNXT_ULP_RF_IDX_GENERIC_TBL_MISS,
2659 tfp_cpu_to_be_64(gen_tbl_miss));
2661 BNXT_TF_DBG(ERR, "Write regfile[%d] failed\n",
2662 BNXT_ULP_RF_IDX_GENERIC_TBL_MISS);
2666 /* add the entry to the flow database */
2668 memset(&fid_parms, 0, sizeof(fid_parms));
2669 fid_parms.direction = tbl->direction;
2670 fid_parms.resource_func = tbl->resource_func;
2671 fid_parms.resource_sub_type = tbl->resource_sub_type;
2672 fid_parms.resource_hndl = key_index;
2673 fid_parms.critical_resource = tbl->critical_resource;
2674 rc = ulp_mapper_fdb_opc_process(parms, tbl, &fid_parms);
2676 BNXT_TF_DBG(ERR, "Fail to add gen ent flowdb %d\n", rc);
2682 ulp_mapper_ctrl_tbl_process(struct bnxt_ulp_mapper_parms *parms,
2683 struct bnxt_ulp_mapper_tbl_info *tbl)
2687 /* process the fdb opcode for alloc push */
2688 if (tbl->fdb_opcode == BNXT_ULP_FDB_OPC_ALLOC_RID_REGFILE) {
2689 rc = ulp_mapper_fdb_opc_alloc_rid(parms, tbl);
2691 BNXT_TF_DBG(ERR, "Failed to do fdb alloc\n");
2699 ulp_mapper_glb_resource_info_init(struct bnxt_ulp_context *ulp_ctx,
2700 struct bnxt_ulp_mapper_data *mapper_data)
2702 struct bnxt_ulp_glb_resource_info *glb_res;
2703 uint32_t num_glb_res_ids, idx;
2706 glb_res = ulp_mapper_glb_resource_info_list_get(&num_glb_res_ids);
2707 if (!glb_res || !num_glb_res_ids) {
2708 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
2712 /* Iterate the global resources and process each one */
2713 for (idx = 0; idx < num_glb_res_ids; idx++) {
2714 switch (glb_res[idx].resource_func) {
2715 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
2716 rc = ulp_mapper_resource_ident_allocate(ulp_ctx,
2720 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
2721 rc = ulp_mapper_resource_index_tbl_alloc(ulp_ctx,
2726 BNXT_TF_DBG(ERR, "Global resource %x not supported\n",
2727 glb_res[idx].resource_func);
2738 * Function to process the memtype opcode of the mapper table.
2739 * returns 1 to skip the table.
2740 * return 0 to continue processing the table.
2745 ulp_mapper_tbl_memtype_opcode_process(struct bnxt_ulp_mapper_parms *parms,
2746 struct bnxt_ulp_mapper_tbl_info *tbl)
2748 enum bnxt_ulp_flow_mem_type mtype = BNXT_ULP_FLOW_MEM_TYPE_INT;
2751 if (bnxt_ulp_cntxt_mem_type_get(parms->ulp_ctx, &mtype)) {
2752 BNXT_TF_DBG(ERR, "Failed to get the mem type\n");
2756 switch (tbl->mem_type_opcode) {
2757 case BNXT_ULP_MEM_TYPE_OPC_EXECUTE_IF_INT:
2758 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_INT)
2761 case BNXT_ULP_MEM_TYPE_OPC_EXECUTE_IF_EXT:
2762 if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT)
2765 case BNXT_ULP_MEM_TYPE_OPC_NOP:
2770 "Invalid arg in mapper in memtype opcode\n");
2777 * Common conditional opcode process routine that is used for both the template
2778 * rejection and table conditional execution.
2781 ulp_mapper_cond_opc_process(struct bnxt_ulp_mapper_parms *parms,
2782 enum bnxt_ulp_cond_opc opc,
2791 case BNXT_ULP_COND_OPC_CF_IS_SET:
2792 if (operand < BNXT_ULP_CF_IDX_LAST) {
2793 *res = ULP_COMP_FLD_IDX_RD(parms, operand);
2795 BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
2800 case BNXT_ULP_COND_OPC_CF_NOT_SET:
2801 if (operand < BNXT_ULP_CF_IDX_LAST) {
2802 *res = !ULP_COMP_FLD_IDX_RD(parms, operand);
2804 BNXT_TF_DBG(ERR, "comp field out of bounds %d\n",
2809 case BNXT_ULP_COND_OPC_ACT_BIT_IS_SET:
2810 if (operand < BNXT_ULP_ACT_BIT_LAST) {
2811 *res = ULP_BITMAP_ISSET(parms->act_bitmap->bits,
2814 BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
2819 case BNXT_ULP_COND_OPC_ACT_BIT_NOT_SET:
2820 if (operand < BNXT_ULP_ACT_BIT_LAST) {
2821 *res = !ULP_BITMAP_ISSET(parms->act_bitmap->bits,
2824 BNXT_TF_DBG(ERR, "action bit out of bounds %d\n",
2829 case BNXT_ULP_COND_OPC_HDR_BIT_IS_SET:
2830 if (operand < BNXT_ULP_HDR_BIT_LAST) {
2831 *res = ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
2834 BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
2839 case BNXT_ULP_COND_OPC_HDR_BIT_NOT_SET:
2840 if (operand < BNXT_ULP_HDR_BIT_LAST) {
2841 *res = !ULP_BITMAP_ISSET(parms->hdr_bitmap->bits,
2844 BNXT_TF_DBG(ERR, "header bit out of bounds %d\n",
2849 case BNXT_ULP_COND_OPC_FIELD_BIT_IS_SET:
2850 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
2852 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
2856 *res = ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
2858 case BNXT_ULP_COND_OPC_FIELD_BIT_NOT_SET:
2859 rc = ulp_mapper_glb_field_tbl_get(parms, operand, &bit);
2861 BNXT_TF_DBG(ERR, "invalid ulp_glb_field_tbl idx %d\n",
2865 *res = !ULP_INDEX_BITMAP_GET(parms->fld_bitmap->bits, bit);
2867 case BNXT_ULP_COND_OPC_RF_IS_SET:
2868 if (!ulp_regfile_read(parms->regfile, operand, ®val)) {
2869 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
2874 case BNXT_ULP_COND_OPC_RF_NOT_SET:
2875 if (!ulp_regfile_read(parms->regfile, operand, ®val)) {
2876 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n", operand);
2881 case BNXT_ULP_COND_OPC_FLOW_PAT_MATCH:
2882 if (parms->flow_pattern_id == operand) {
2883 BNXT_TF_DBG(ERR, "field pattern match failed %x\n",
2884 parms->flow_pattern_id);
2888 case BNXT_ULP_COND_OPC_ACT_PAT_MATCH:
2889 if (parms->act_pattern_id == operand) {
2890 BNXT_TF_DBG(ERR, "act pattern match failed %x\n",
2891 parms->act_pattern_id);
2896 BNXT_TF_DBG(ERR, "Invalid conditional opcode %d\n", opc);
2904 * Processes a list of conditions and returns both a status and result of the
2905 * list. The status must be checked prior to verifying the result.
2907 * returns 0 for success, negative on failure
2908 * returns res = 1 for true, res = 0 for false.
2911 ulp_mapper_cond_opc_list_process(struct bnxt_ulp_mapper_parms *parms,
2912 enum bnxt_ulp_cond_list_opc list_opc,
2913 struct bnxt_ulp_mapper_cond_info *list,
2918 int32_t rc = 0, trc = 0;
2921 case BNXT_ULP_COND_LIST_OPC_AND:
2922 /* AND Defaults to true. */
2925 case BNXT_ULP_COND_LIST_OPC_OR:
2926 /* OR Defaults to false. */
2929 case BNXT_ULP_COND_LIST_OPC_TRUE:
2932 case BNXT_ULP_COND_LIST_OPC_FALSE:
2936 BNXT_TF_DBG(ERR, "Invalid conditional list opcode %d\n",
2941 for (i = 0; i < num; i++) {
2942 rc = ulp_mapper_cond_opc_process(parms,
2943 list[i].cond_opcode,
2944 list[i].cond_operand,
2949 if (list_opc == BNXT_ULP_COND_LIST_OPC_AND) {
2950 /* early return if result is ever zero */
2956 /* early return if result is ever non-zero */
2968 * Processes conflict resolution and returns both a status and result.
2969 * The status must be checked prior to verifying the result.
2971 * returns 0 for success, negative on failure
2972 * returns res = 1 for true, res = 0 for false.
2975 ulp_mapper_conflict_resolution_process(struct bnxt_ulp_mapper_parms *parms,
2976 struct bnxt_ulp_mapper_tbl_info *tbl,
2981 uint64_t comp_sig_id;
2984 switch (tbl->accept_opcode) {
2985 case BNXT_ULP_ACCEPT_OPC_ALWAYS:
2988 case BNXT_ULP_ACCEPT_OPC_FLOW_SIG_ID_MATCH:
2989 /* perform the signature validation*/
2990 if (tbl->resource_func ==
2991 BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE) {
2992 /* Perform the check that generic table is hit or not */
2993 if (!ulp_regfile_read(parms->regfile,
2994 BNXT_ULP_RF_IDX_GENERIC_TBL_MISS,
2996 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
2997 BNXT_ULP_RF_IDX_GENERIC_TBL_MISS);
3001 /* not a hit so no need to check flow sign*/
3006 /* compare the new flow signature against stored one */
3007 if (!ulp_regfile_read(parms->regfile,
3008 BNXT_ULP_RF_IDX_FLOW_SIG_ID,
3010 BNXT_TF_DBG(ERR, "regfile[%d] read oob\n",
3011 BNXT_ULP_RF_IDX_FLOW_SIG_ID);
3014 comp_sig_id = ULP_COMP_FLD_IDX_RD(parms,
3015 BNXT_ULP_CF_IDX_FLOW_SIG_ID);
3016 regval = tfp_be_to_cpu_64(regval);
3017 if (comp_sig_id == regval)
3020 BNXT_TF_DBG(ERR, "failed signature match %x:%x\n",
3021 (uint32_t)comp_sig_id, (uint32_t)regval);
3024 BNXT_TF_DBG(ERR, "Invalid accept opcode %d\n",
3025 tbl->accept_opcode);
3032 ulp_mapper_tbls_process(struct bnxt_ulp_mapper_parms *parms, uint32_t tid)
3034 struct bnxt_ulp_mapper_cond_info *cond_tbls = NULL;
3035 enum bnxt_ulp_cond_list_opc cond_opc;
3036 struct bnxt_ulp_mapper_tbl_info *tbls;
3037 struct bnxt_ulp_mapper_tbl_info *tbl;
3038 uint32_t num_tbls, tbl_idx, num_cond_tbls;
3039 int32_t rc = -EINVAL, cond_rc = 0;
3040 int32_t cond_goto = 1;
3042 cond_tbls = ulp_mapper_tmpl_reject_list_get(parms, tid,
3046 * Process the reject list if exists, otherwise assume that the
3047 * template is allowed.
3049 if (cond_tbls && num_cond_tbls) {
3050 rc = ulp_mapper_cond_opc_list_process(parms,
3058 /* Reject the template if True */
3060 BNXT_TF_DBG(ERR, "%s Template %d rejected.\n",
3061 ulp_mapper_tmpl_name_str(parms->tmpl_type),
3067 tbls = ulp_mapper_tbl_list_get(parms, tid, &num_tbls);
3068 if (!tbls || !num_tbls) {
3069 BNXT_TF_DBG(ERR, "No %s tables for %d:%d\n",
3070 ulp_mapper_tmpl_name_str(parms->tmpl_type),
3071 parms->dev_id, tid);
3075 for (tbl_idx = 0; tbl_idx < num_tbls && cond_goto;) {
3076 tbl = &tbls[tbl_idx];
3077 /* Handle the table level opcodes to determine if required. */
3078 if (ulp_mapper_tbl_memtype_opcode_process(parms, tbl)) {
3079 cond_goto = tbl->execute_info.cond_false_goto;
3080 goto next_iteration;
3083 cond_tbls = ulp_mapper_tbl_execute_list_get(parms, tbl,
3086 rc = ulp_mapper_cond_opc_list_process(parms, cond_opc,
3087 cond_tbls, num_cond_tbls,
3090 BNXT_TF_DBG(ERR, "Failed to process cond opc list "
3094 /* Skip the table if False */
3096 cond_goto = tbl->execute_info.cond_false_goto;
3097 goto next_iteration;
3100 switch (tbl->resource_func) {
3101 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
3102 rc = ulp_mapper_tcam_tbl_process(parms, tbl);
3104 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
3105 rc = ulp_mapper_em_tbl_process(parms, tbl);
3107 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3108 rc = ulp_mapper_index_tbl_process(parms, tbl);
3110 case BNXT_ULP_RESOURCE_FUNC_IF_TABLE:
3111 rc = ulp_mapper_if_tbl_process(parms, tbl);
3113 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
3114 rc = ulp_mapper_gen_tbl_process(parms, tbl);
3116 case BNXT_ULP_RESOURCE_FUNC_CTRL_TABLE:
3117 rc = ulp_mapper_ctrl_tbl_process(parms, tbl);
3119 case BNXT_ULP_RESOURCE_FUNC_INVALID:
3123 BNXT_TF_DBG(ERR, "Unexpected mapper resource %d\n",
3124 tbl->resource_func);
3130 BNXT_TF_DBG(ERR, "Resource type %d failed\n",
3131 tbl->resource_func);
3135 /* perform the post table process */
3136 rc = ulp_mapper_conflict_resolution_process(parms, tbl,
3138 if (rc || !cond_rc) {
3139 BNXT_TF_DBG(ERR, "Failed due to conflict resolution\n");
3144 if (cond_goto < 0 && ((int32_t)tbl_idx + cond_goto) < 0) {
3145 BNXT_TF_DBG(ERR, "invalid conditional goto %d\n",
3149 tbl_idx += cond_goto;
3154 BNXT_TF_DBG(ERR, "%s tables failed creation for %d:%d\n",
3155 ulp_mapper_tmpl_name_str(parms->tmpl_type),
3156 parms->dev_id, tid);
3161 ulp_mapper_resource_free(struct bnxt_ulp_context *ulp,
3163 struct ulp_flow_db_res_params *res)
3169 BNXT_TF_DBG(ERR, "Unable to free resource\n ");
3173 tfp = bnxt_ulp_cntxt_tfp_get(ulp);
3175 BNXT_TF_DBG(ERR, "Unable to free resource failed to get tfp\n");
3179 switch (res->resource_func) {
3180 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
3181 rc = ulp_mapper_tcam_entry_free(ulp, tfp, res);
3183 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
3184 rc = ulp_mapper_em_entry_free(ulp, tfp, res);
3186 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
3187 rc = ulp_mapper_index_entry_free(ulp, tfp, res);
3189 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
3190 rc = ulp_mapper_ident_free(ulp, tfp, res);
3192 case BNXT_ULP_RESOURCE_FUNC_HW_FID:
3193 rc = ulp_mapper_mark_free(ulp, res);
3195 case BNXT_ULP_RESOURCE_FUNC_PARENT_FLOW:
3196 rc = ulp_mapper_parent_flow_free(ulp, fid, res);
3198 case BNXT_ULP_RESOURCE_FUNC_CHILD_FLOW:
3199 rc = ulp_mapper_child_flow_free(ulp, fid, res);
3201 case BNXT_ULP_RESOURCE_FUNC_GENERIC_TABLE:
3202 rc = ulp_mapper_gen_tbl_res_free(ulp, res);
3212 ulp_mapper_resources_free(struct bnxt_ulp_context *ulp_ctx,
3213 enum bnxt_ulp_fdb_type flow_type,
3216 struct ulp_flow_db_res_params res_parms = { 0 };
3220 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
3225 * Set the critical resource on the first resource del, then iterate
3226 * while status is good
3228 if (flow_type != BNXT_ULP_FDB_TYPE_RID)
3229 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_YES;
3231 rc = ulp_flow_db_resource_del(ulp_ctx, flow_type, fid, &res_parms);
3235 * This is unexpected on the first call to resource del.
3236 * It likely means that the flow did not exist in the flow db.
3238 BNXT_TF_DBG(ERR, "Flow[%d][0x%08x] failed to free (rc=%d)\n",
3239 flow_type, fid, rc);
3244 trc = ulp_mapper_resource_free(ulp_ctx, fid, &res_parms);
3247 * On fail, we still need to attempt to free the
3248 * remaining resources. Don't return
3251 "Flow[%d][0x%x] Res[%d][0x%016" PRIX64
3252 "] failed rc=%d.\n",
3253 flow_type, fid, res_parms.resource_func,
3254 res_parms.resource_hndl, trc);
3256 /* All subsequent call require the non-critical_resource */
3257 res_parms.critical_resource = BNXT_ULP_CRITICAL_RESOURCE_NO;
3259 rc = ulp_flow_db_resource_del(ulp_ctx,
3265 /* Free the Flow ID since we've removed all resources */
3266 rc = ulp_flow_db_fid_free(ulp_ctx, flow_type, fid);
3272 ulp_mapper_glb_resource_info_deinit(struct bnxt_ulp_context *ulp_ctx,
3273 struct bnxt_ulp_mapper_data *mapper_data)
3275 struct bnxt_ulp_mapper_glb_resource_entry *ent;
3276 struct ulp_flow_db_res_params res;
3279 /* Iterate the global resources and process each one */
3280 for (dir = TF_DIR_RX; dir < TF_DIR_MAX; dir++) {
3281 for (idx = 0; idx < BNXT_ULP_GLB_RESOURCE_TBL_MAX_SZ;
3283 ent = &mapper_data->glb_res_tbl[dir][idx];
3284 if (ent->resource_func ==
3285 BNXT_ULP_RESOURCE_FUNC_INVALID)
3287 memset(&res, 0, sizeof(struct ulp_flow_db_res_params));
3288 res.resource_func = ent->resource_func;
3289 res.direction = dir;
3290 res.resource_type = ent->resource_type;
3291 /*convert it from BE to cpu */
3293 tfp_be_to_cpu_64(ent->resource_hndl);
3294 ulp_mapper_resource_free(ulp_ctx, 0, &res);
3300 ulp_mapper_flow_destroy(struct bnxt_ulp_context *ulp_ctx,
3301 enum bnxt_ulp_fdb_type flow_type,
3307 BNXT_TF_DBG(ERR, "Invalid parms, unable to free flow\n");
3311 rc = ulp_mapper_resources_free(ulp_ctx, flow_type, fid);
3315 /* Function to handle the default global templates that are allocated during
3316 * the startup and reused later.
3319 ulp_mapper_glb_template_table_init(struct bnxt_ulp_context *ulp_ctx)
3321 uint32_t *glbl_tmpl_list;
3322 uint32_t num_glb_tmpls, idx, dev_id;
3323 struct bnxt_ulp_mapper_parms parms;
3324 struct bnxt_ulp_mapper_data *mapper_data;
3327 glbl_tmpl_list = ulp_mapper_glb_template_table_get(&num_glb_tmpls);
3328 if (!glbl_tmpl_list || !num_glb_tmpls)
3329 return rc; /* No global templates to process */
3331 /* Get the device id from the ulp context */
3332 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) {
3333 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
3337 mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3339 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
3343 /* Iterate the global resources and process each one */
3344 for (idx = 0; idx < num_glb_tmpls; idx++) {
3345 /* Initialize the parms structure */
3346 memset(&parms, 0, sizeof(parms));
3347 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3348 parms.ulp_ctx = ulp_ctx;
3349 parms.dev_id = dev_id;
3350 parms.mapper_data = mapper_data;
3351 parms.flow_type = BNXT_ULP_FDB_TYPE_DEFAULT;
3352 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
3354 /* Get the class table entry from dev id and class id */
3355 parms.class_tid = glbl_tmpl_list[idx];
3357 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
3358 if (!parms.device_params) {
3359 BNXT_TF_DBG(ERR, "No device for device id %d\n",
3364 rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
3371 /* Function to handle the mapping of the Flow to be compatible
3372 * with the underlying hardware.
3375 ulp_mapper_flow_create(struct bnxt_ulp_context *ulp_ctx,
3376 struct bnxt_ulp_mapper_create_parms *cparms)
3378 struct bnxt_ulp_mapper_parms parms;
3379 struct ulp_regfile regfile;
3380 int32_t rc = 0, trc;
3382 if (!ulp_ctx || !cparms)
3385 /* Initialize the parms structure */
3386 memset(&parms, 0, sizeof(parms));
3387 parms.act_prop = cparms->act_prop;
3388 parms.act_bitmap = cparms->act;
3389 parms.hdr_bitmap = cparms->hdr_bitmap;
3390 parms.regfile = ®file;
3391 parms.hdr_field = cparms->hdr_field;
3392 parms.fld_bitmap = cparms->fld_bitmap;
3393 parms.comp_fld = cparms->comp_fld;
3394 parms.tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3395 parms.ulp_ctx = ulp_ctx;
3396 parms.act_tid = cparms->act_tid;
3397 parms.class_tid = cparms->class_tid;
3398 parms.flow_type = cparms->flow_type;
3399 parms.parent_flow = cparms->parent_flow;
3400 parms.parent_fid = cparms->parent_fid;
3401 parms.fid = cparms->flow_id;
3402 parms.tun_idx = cparms->tun_idx;
3403 parms.app_priority = cparms->app_priority;
3404 parms.flow_pattern_id = cparms->flow_pattern_id;
3405 parms.act_pattern_id = cparms->act_pattern_id;
3407 /* Get the device id from the ulp context */
3408 if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &parms.dev_id)) {
3409 BNXT_TF_DBG(ERR, "Invalid ulp context\n");
3413 /* Get the device params, it will be used in later processing */
3414 parms.device_params = bnxt_ulp_device_params_get(parms.dev_id);
3415 if (!parms.device_params) {
3416 BNXT_TF_DBG(ERR, "No device parms for device id %d\n",
3422 * Get the mapper data for dynamic mapper data such as default
3425 parms.mapper_data = (struct bnxt_ulp_mapper_data *)
3426 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3427 if (!parms.mapper_data) {
3428 BNXT_TF_DBG(ERR, "Failed to get the ulp mapper data\n");
3432 /* initialize the registry file for further processing */
3433 if (!ulp_regfile_init(parms.regfile)) {
3434 BNXT_TF_DBG(ERR, "regfile initialization failed.\n");
3438 /* Process the action template list from the selected action table*/
3439 if (parms.act_tid) {
3440 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_ACTION;
3441 /* Process the action template tables */
3442 rc = ulp_mapper_tbls_process(&parms, parms.act_tid);
3447 if (parms.class_tid) {
3448 parms.tmpl_type = BNXT_ULP_TEMPLATE_TYPE_CLASS;
3450 /* Process the class template tables.*/
3451 rc = ulp_mapper_tbls_process(&parms, parms.class_tid);
3456 /* setup the parent-child details */
3457 if (parms.parent_flow) {
3458 /* create a parent flow details */
3459 rc = ulp_flow_db_parent_flow_create(&parms);
3462 } else if (parms.parent_fid) {
3463 /* create a child flow details */
3464 rc = ulp_flow_db_child_flow_create(&parms);
3472 /* Free all resources that were allocated during flow creation */
3473 trc = ulp_mapper_flow_destroy(ulp_ctx, parms.flow_type,
3476 BNXT_TF_DBG(ERR, "Failed to free all resources rc=%d\n", trc);
3482 ulp_mapper_init(struct bnxt_ulp_context *ulp_ctx)
3484 struct bnxt_ulp_mapper_data *data;
3491 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3495 data = rte_zmalloc("ulp_mapper_data",
3496 sizeof(struct bnxt_ulp_mapper_data), 0);
3498 BNXT_TF_DBG(ERR, "Failed to allocate the mapper data\n");
3502 if (bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, data)) {
3503 BNXT_TF_DBG(ERR, "Failed to set mapper data in context\n");
3504 /* Don't call deinit since the prof_func wasn't allocated. */
3509 /* Allocate the global resource ids */
3510 rc = ulp_mapper_glb_resource_info_init(ulp_ctx, data);
3512 BNXT_TF_DBG(ERR, "Failed to initialize global resource ids\n");
3516 /* Allocate the generic table list */
3517 rc = ulp_mapper_generic_tbl_list_init(data);
3519 BNXT_TF_DBG(ERR, "Failed to initialize generic tbl list\n");
3523 /* Allocate global template table entries */
3524 rc = ulp_mapper_glb_template_table_init(ulp_ctx);
3526 BNXT_TF_DBG(ERR, "Failed to initialize global templates\n");
3532 /* Ignore the return code in favor of returning the original error. */
3533 ulp_mapper_deinit(ulp_ctx);
3538 ulp_mapper_deinit(struct bnxt_ulp_context *ulp_ctx)
3540 struct bnxt_ulp_mapper_data *data;
3545 "Failed to acquire ulp context, so data may "
3546 "not be released.\n");
3550 data = (struct bnxt_ulp_mapper_data *)
3551 bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
3553 /* Go ahead and return since there is no allocated data. */
3554 BNXT_TF_DBG(ERR, "No data appears to have been allocated.\n");
3558 tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
3560 BNXT_TF_DBG(ERR, "Failed to acquire tfp.\n");
3561 /* Free the mapper data regardless of errors. */
3562 goto free_mapper_data;
3565 /* Free the global resource info table entries */
3566 ulp_mapper_glb_resource_info_deinit(ulp_ctx, data);
3569 /* Free the generic table */
3570 (void)ulp_mapper_generic_tbl_list_deinit(data);
3573 /* Reset the data pointer within the ulp_ctx. */
3574 bnxt_ulp_cntxt_ptr2_mapper_data_set(ulp_ctx, NULL);